Merge remote-tracking branch 'origin/4.9'

Conflicts:
	qbs/modules/qtc/qtc.qbs
	qtcreator.pri
	src/plugins/debugger/debuggerkitinformation.cpp
	src/plugins/languageclient/languageclientmanager.cpp
	src/plugins/plugins.pro
	src/plugins/projectexplorer/kit.cpp
	src/plugins/projectexplorer/kitmanager.cpp

Change-Id: I66fb941202991f35f7d7761430b21e42dfc678a8
This commit is contained in:
Eike Ziller
2019-03-14 15:14:40 +01:00
154 changed files with 2211 additions and 1068 deletions

View File

@@ -8,6 +8,8 @@
# Use ../../tests/manual/clang-format-for-qtc/test.cpp for documenting problems # Use ../../tests/manual/clang-format-for-qtc/test.cpp for documenting problems
# or testing changes. # or testing changes.
# #
# In case you update this configuration please also update the qtcStyle() in src\plugins\clangformat\clangformatutils.cpp
#
# [1] https://doc-snapshots.qt.io/qtcreator-extending/coding-style.html # [1] https://doc-snapshots.qt.io/qtcreator-extending/coding-style.html
# [2] https://clang.llvm.org/docs/ClangFormatStyleOptions.html # [2] https://clang.llvm.org/docs/ClangFormatStyleOptions.html
# #

View File

@@ -34,9 +34,10 @@ Prerequisites:
* Python 3.5 or later (optional, needed for the python enabled debug helper) * Python 3.5 or later (optional, needed for the python enabled debug helper)
* On Mac OS X: latest Xcode * On Mac OS X: latest Xcode
* On Linux: g++ 5.3 or later * On Linux: g++ 5.3 or later
* LLVM/Clang 6.0.0 or later (optional, needed for the Clang Code Model, see the * LLVM/Clang 7.0.0 or later (optional, needed for the Clang Code Model, Clang Tools, ClangFormat,
section "Get LLVM/Clang for the Clang Code Model") Clang PCH Manager and Clang Refactoring plugins, see the section
* CMake (only for manual builds of LLVM/Clang) "Get LLVM/Clang for the Clang Code Model")
* CMake (only for manual builds of LLVM/Clang)
* Qbs 1.7.x (optional, sources also contain Qbs itself) * Qbs 1.7.x (optional, sources also contain Qbs itself)
The installed toolchains have to match the one Qt was compiled with. The installed toolchains have to match the one Qt was compiled with.
@@ -49,6 +50,10 @@ You can build Qt Creator with
export QBS_INSTALL_DIR=/path/to/qbs export QBS_INSTALL_DIR=/path/to/qbs
# Optional, needed for the Python enabled dumper on Windows # Optional, needed for the Python enabled dumper on Windows
set PYTHON_INSTALL_DIR=C:\path\to\python set PYTHON_INSTALL_DIR=C:\path\to\python
# Optional, needed to use system KSyntaxHighlighting:
set KSYNTAXHIGHLIGHTING_LIB_DIR to folder holding the KSyntaxHighlighting library
# if automatic deducing of include folder fails set KSYNTAXHIGHLIGHTING_INCLUDE_DIR as well
# both variables can also be passed as qmake variables
cd $SOURCE_DIRECTORY cd $SOURCE_DIRECTORY
qmake -r qmake -r
@@ -220,7 +225,7 @@ or using shadow builds.
## Get LLVM/Clang for the Clang Code Model ## Get LLVM/Clang for the Clang Code Model
The Clang Code Model depends on the LLVM/Clang libraries. The currently The Clang Code Model depends on the LLVM/Clang libraries. The currently
supported LLVM/Clang version is 6.0. supported LLVM/Clang version is 7.0.
### Prebuilt LLVM/Clang packages ### Prebuilt LLVM/Clang packages
@@ -247,9 +252,9 @@ GCC 4 binaries. On Ubuntu, you can download the package from
http://apt.llvm.org/ with: http://apt.llvm.org/ with:
wget -O - http://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - wget -O - http://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo apt-add-repository "deb http://apt.llvm.org/`lsb_release -cs`/ llvm-toolchain-`lsb_release -cs`-6.0 main" sudo apt-add-repository "deb http://apt.llvm.org/`lsb_release -cs`/ llvm-toolchain-`lsb_release -cs`-7.0 main"
sudo apt-get update sudo apt-get update
sudo apt-get install llvm-6.0 libclang-6.0-dev sudo apt-get install llvm-7.0 libclang-7.0-dev
There is a workaround to set _GLIBCXX_USE_CXX11_ABI to 1 or 0, but we recommend There is a workaround to set _GLIBCXX_USE_CXX11_ABI to 1 or 0, but we recommend
to download the package from http://apt.llvm.org/. to download the package from http://apt.llvm.org/.

10
dist/changes-4.9.0.md vendored
View File

@@ -52,6 +52,10 @@ QMake Projects
* Fixed updating of `LD_LIBRARY_PATH` environment variable (QTCREATORBUG-21475) * Fixed updating of `LD_LIBRARY_PATH` environment variable (QTCREATORBUG-21475)
* Fixed updating of project tree in case of wildcards in corresponding QMake * Fixed updating of project tree in case of wildcards in corresponding QMake
variable (QTCREATORBUG-21603) variable (QTCREATORBUG-21603)
* Fixed issues with project tree when files are directly added to `RESOURCES`
(QTCREATORBUG-20103)
* Fixed that importing build unnecessarily created temporary kit
(QTCREATORBUG-18153)
CMake Projects CMake Projects
@@ -78,6 +82,8 @@ C++ Support
* Clang Code Model * Clang Code Model
* Added buttons for copying and ignoring diagnostics to tooltip * Added buttons for copying and ignoring diagnostics to tooltip
* Fixed issue with high memory consumption (QTCREATORBUG-19543) * Fixed issue with high memory consumption (QTCREATORBUG-19543)
* Fixed inconsistency between `Follow Symbol` and `Ctrl + Click`
(QTCREATORBUG-21637)
* Clang Format * Clang Format
* Added option to format code instead of only indenting code * Added option to format code instead of only indenting code
@@ -98,6 +104,9 @@ Nim Support
Debugging Debugging
* Fixed that debugger toolbar could force large minimum window size
(QTCREATORBUG-21885)
* Added pretty printing of `QSizePolicy`
* GDB * GDB
* Added support for rvalue references in function arguments * Added support for rvalue references in function arguments
* LLDB * LLDB
@@ -167,6 +176,7 @@ Windows
* Added support for MSVC 2019 * Added support for MSVC 2019
* Changed toolchain detection to use `vswhere` by default, which is recommended * Changed toolchain detection to use `vswhere` by default, which is recommended
by Microsoft by Microsoft
* Fixed issue with UNC paths in `.pro` files (QTCREATORBUG-21881)
Linux Linux

View File

@@ -109,15 +109,19 @@ linux {
macx { macx {
APPBUNDLE = "$$OUT_PWD/bin/$${IDE_APP_TARGET}.app" APPBUNDLE = "$$OUT_PWD/bin/$${IDE_APP_TARGET}.app"
BINDIST_SOURCE = "$$OUT_PWD/bin/$${IDE_APP_TARGET}.app" BINDIST_SOURCE.release = "$$OUT_PWD/bin/$${IDE_APP_TARGET}.app"
BINDIST_SOURCE.debug = "$$OUT_PWD/bin"
BINDIST_EXCLUDE_ARG.debug = "--exclude-toplevel"
deployqt.commands = $$PWD/scripts/deployqtHelper_mac.sh \"$${APPBUNDLE}\" \"$$[QT_INSTALL_BINS]\" \"$$[QT_INSTALL_TRANSLATIONS]\" \"$$[QT_INSTALL_PLUGINS]\" \"$$[QT_INSTALL_IMPORTS]\" \"$$[QT_INSTALL_QML]\" deployqt.commands = $$PWD/scripts/deployqtHelper_mac.sh \"$${APPBUNDLE}\" \"$$[QT_INSTALL_BINS]\" \"$$[QT_INSTALL_TRANSLATIONS]\" \"$$[QT_INSTALL_PLUGINS]\" \"$$[QT_INSTALL_IMPORTS]\" \"$$[QT_INSTALL_QML]\"
codesign.commands = codesign --deep -s \"$(SIGNING_IDENTITY)\" $(SIGNING_FLAGS) \"$${APPBUNDLE}\" codesign.commands = codesign --deep -s \"$(SIGNING_IDENTITY)\" $(SIGNING_FLAGS) \"$${APPBUNDLE}\"
dmg.commands = python -u \"$$PWD/scripts/makedmg.py\" \"$${BASENAME}.dmg\" \"Qt Creator\" \"$$IDE_SOURCE_TREE\" \"$$OUT_PWD/bin\" dmg.commands = python -u \"$$PWD/scripts/makedmg.py\" \"$${BASENAME}.dmg\" \"Qt Creator\" \"$$IDE_SOURCE_TREE\" \"$$OUT_PWD/bin\"
#dmg.depends = deployqt #dmg.depends = deployqt
QMAKE_EXTRA_TARGETS += codesign dmg QMAKE_EXTRA_TARGETS += codesign dmg
} else { } else {
BINDIST_SOURCE = "$(INSTALL_ROOT)$$QTC_PREFIX" BINDIST_SOURCE.release = "$(INSTALL_ROOT)$$QTC_PREFIX"
BINDIST_EXCLUDE_ARG = "--exclude-toplevel" BINDIST_EXCLUDE_ARG.release = "--exclude-toplevel"
BINDIST_SOURCE.debug = $${BINDIST_SOURCE.release}
BINDIST_EXCLUDE_ARG.debug = $${BINDIST_EXCLUDE_ARG.release}
deployqt.commands = python -u $$PWD/scripts/deployqt.py -i \"$(INSTALL_ROOT)$$QTC_PREFIX/bin/$${IDE_APP_TARGET}\" \"$(QMAKE)\" deployqt.commands = python -u $$PWD/scripts/deployqt.py -i \"$(INSTALL_ROOT)$$QTC_PREFIX/bin/$${IDE_APP_TARGET}\" \"$(QMAKE)\"
deployqt.depends = install deployqt.depends = install
win32 { win32 {
@@ -140,9 +144,9 @@ isEmpty(INSTALLER_ARCHIVE_FROM_ENV) {
INSTALLER_ARCHIVE_DEBUG = $$INSTALLER_ARCHIVE INSTALLER_ARCHIVE_DEBUG = $$INSTALLER_ARCHIVE
INSTALLER_ARCHIVE_DEBUG ~= s/(.*)[.]7z/\1-debug.7z INSTALLER_ARCHIVE_DEBUG ~= s/(.*)[.]7z/\1-debug.7z
bindist.commands = python -u $$PWD/scripts/createDistPackage.py $$OUT_PWD/$${BASENAME}.7z \"$$BINDIST_SOURCE\" bindist.commands = python -u $$PWD/scripts/createDistPackage.py $$OUT_PWD/$${BASENAME}.7z \"$${BINDIST_SOURCE.release}\"
bindist_installer.commands = python -u $$PWD/scripts/createDistPackage.py $$BINDIST_EXCLUDE_ARG $${INSTALLER_ARCHIVE} \"$$BINDIST_SOURCE\" bindist_installer.commands = python -u $$PWD/scripts/createDistPackage.py $${BINDIST_EXCLUDE_ARG.release} $${INSTALLER_ARCHIVE} \"$${BINDIST_SOURCE.release}\"
bindist_debug.commands = python -u $$PWD/scripts/createDistPackage.py --debug $$BINDIST_EXCLUDE_ARG $${INSTALLER_ARCHIVE_DEBUG} \"$$BINDIST_SOURCE\" bindist_debug.commands = python -u $$PWD/scripts/createDistPackage.py --debug $${BINDIST_EXCLUDE_ARG.debug} $${INSTALLER_ARCHIVE_DEBUG} \"$${BINDIST_SOURCE.debug}\"
win32 { win32 {
deployqt.commands ~= s,/,\\\\,g deployqt.commands ~= s,/,\\\\,g

50
scripts/flake2tasks.py Executable file
View File

@@ -0,0 +1,50 @@
#!/usr/bin/env python
############################################################################
#
# Copyright (C) 2019 The Qt Company Ltd.
# Contact: https://www.qt.io/licensing/
#
# This file is part of Qt Creator.
#
# Commercial License Usage
# Licensees holding valid commercial Qt licenses may use this file in
# accordance with the commercial license agreement provided with the
# Software or, alternatively, in accordance with the terms contained in
# a written agreement between you and The Qt Company. For licensing terms
# and conditions see https://www.qt.io/terms-conditions. For further
# information use the contact form at https://www.qt.io/contact-us.
#
# GNU General Public License Usage
# Alternatively, this file may be used under the terms of the GNU
# General Public License version 3 as published by the Free Software
# Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
# included in the packaging of this file. Please review the following
# information to ensure the GNU General Public License requirements will
# be met: https://www.gnu.org/licenses/gpl-3.0.html.
#
############################################################################
'''
flake2tasks.py - Convert flake8 warnings into Qt Creator task files.
SYNOPSIS
flake2tasks.py < logfile > taskfile
'''
import sys
import re
if __name__ == '__main__':
pattern = re.compile(r'^([^:]+):(\d+):\d+: E\d+ (.*)$')
while True:
line = sys.stdin.readline().rstrip()
if not line:
break
match = pattern.match(line)
if match:
file_name = match.group(1).replace('\\', '/')
line_number = match.group(2)
text = match.group(3)
output = "{}\t{}\twarn\t{}".format(file_name, line_number, text)
print(output)

View File

@@ -957,6 +957,12 @@ class Dumper(DumperBase):
return return
self.report('pid="%s"' % self.process.GetProcessID()) self.report('pid="%s"' % self.process.GetProcessID())
self.reportState('enginerunandinferiorrunok') self.reportState('enginerunandinferiorrunok')
if self.target is not None:
broadcaster = self.target.GetBroadcaster()
listener = self.debugger.GetListener()
broadcaster.AddListener(listener, lldb.SBTarget.eBroadcastBitBreakpointChanged)
listener.StartListeningForEvents(broadcaster, lldb.SBTarget.eBroadcastBitBreakpointChanged)
def loop(self): def loop(self):
event = lldb.SBEvent() event = lldb.SBEvent()
@@ -1116,6 +1122,11 @@ class Dumper(DumperBase):
# logview pane feature. # logview pane feature.
self.report('token(\"%s\")' % args["token"]) self.report('token(\"%s\")' % args["token"])
def reportBreakpointUpdate(self, bp):
self.report('breakpointmodified={%s}' % self.describeBreakpoint(bp))
def readRawMemory(self, address, size): def readRawMemory(self, address, size):
if size == 0: if size == 0:
return bytes() return bytes()
@@ -1288,7 +1299,20 @@ class Dumper(DumperBase):
self.process.Kill() self.process.Kill()
self.reportResult('', args) self.reportResult('', args)
def handleBreakpointEvent(self, event):
eventType = lldb.SBBreakpoint.GetBreakpointEventTypeFromEvent(event)
# handle only the resolved locations for now..
if eventType & lldb.eBreakpointEventTypeLocationsResolved:
bp = lldb.SBBreakpoint.GetBreakpointFromEvent(event)
if bp is not None:
self.reportBreakpointUpdate(bp)
def handleEvent(self, event): def handleEvent(self, event):
if lldb.SBBreakpoint.EventIsBreakpointEvent(event):
self.handleBreakpointEvent(event)
return
out = lldb.SBStream() out = lldb.SBStream()
event.GetDescription(out) event.GetDescription(out)
#warn("EVENT: %s" % event) #warn("EVENT: %s" % event)

View File

@@ -3,7 +3,7 @@
"supportedProjectTypes": [ "PythonProject" ], "supportedProjectTypes": [ "PythonProject" ],
"id": "U.QtForPythonApplicationEmpty", "id": "U.QtForPythonApplicationEmpty",
"category": "F.Application", "category": "F.Application",
"trDescription": "Creates a Qt for Python application that only the main code for a QApplication", "trDescription": "Creates a Qt for Python application that contains only the main code for a QApplication.",
"trDisplayName": "Qt for Python - Empty", "trDisplayName": "Qt for Python - Empty",
"trDisplayCategory": "Application", "trDisplayCategory": "Application",
"icon": "icon.png", "icon": "icon.png",

View File

@@ -5,8 +5,9 @@ TEMPLATE = app
CONFIG += qtc_runnable sliced_bundle CONFIG += qtc_runnable sliced_bundle
TARGET = $$IDE_APP_TARGET TARGET = $$IDE_APP_TARGET
DESTDIR = $$IDE_APP_PATH DESTDIR = $$IDE_APP_PATH
VERSION = $$QTCREATOR_VERSION
QT -= testlib QT -= testlib
# work around QTBUG-74265
win32: VERSION=
HEADERS += ../tools/qtcreatorcrashhandler/crashhandlersetup.h HEADERS += ../tools/qtcreatorcrashhandler/crashhandlersetup.h
SOURCES += main.cpp ../tools/qtcreatorcrashhandler/crashhandlersetup.cpp SOURCES += main.cpp ../tools/qtcreatorcrashhandler/crashhandlersetup.cpp

View File

@@ -51,6 +51,7 @@ public:
commandLine.reserve(1024); commandLine.reserve(1024);
addCompiler(projectInfo.language); addCompiler(projectInfo.language);
disableWarnings();
addToolChainArguments(toolChainArguments); addToolChainArguments(toolChainArguments);
addExtraFlags(); addExtraFlags();
addLanguage(projectInfo, sourceType); addLanguage(projectInfo, sourceType);
@@ -74,6 +75,8 @@ public:
commandLine.emplace_back("clang"); commandLine.emplace_back("clang");
} }
void disableWarnings() { commandLine.emplace_back("-w"); }
void addToolChainArguments(const Utils::SmallStringVector &toolChainArguments) void addToolChainArguments(const Utils::SmallStringVector &toolChainArguments)
{ {
for (Utils::SmallStringView argument : toolChainArguments) for (Utils::SmallStringView argument : toolChainArguments)

View File

@@ -143,6 +143,8 @@ public:
const Sqlite::Column &projectPartIdColumn = table.addColumn("projectPartId", Sqlite::ColumnType::Integer); const Sqlite::Column &projectPartIdColumn = table.addColumn("projectPartId", Sqlite::ColumnType::Integer);
const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer); const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer);
table.addColumn("sourceType", Sqlite::ColumnType::Integer); table.addColumn("sourceType", Sqlite::ColumnType::Integer);
table.addColumn("pchCreationTimeStamp", Sqlite::ColumnType::Integer);
table.addColumn("hasMissingIncludes", Sqlite::ColumnType::Integer);
table.addUniqueIndex({sourceIdColumn, projectPartIdColumn}); table.addUniqueIndex({sourceIdColumn, projectPartIdColumn});
table.addIndex({projectPartIdColumn}); table.addIndex({projectPartIdColumn});
@@ -168,11 +170,11 @@ public:
Sqlite::Table table; Sqlite::Table table;
table.setUseIfNotExists(true); table.setUseIfNotExists(true);
table.setName("fileStatuses"); table.setName("fileStatuses");
table.addColumn("sourceId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey); table.addColumn("sourceId",
Sqlite::ColumnType::Integer,
Sqlite::Contraint::PrimaryKey);
table.addColumn("size", Sqlite::ColumnType::Integer); table.addColumn("size", Sqlite::ColumnType::Integer);
table.addColumn("lastModified", Sqlite::ColumnType::Integer); table.addColumn("lastModified", Sqlite::ColumnType::Integer);
table.addColumn("buildDependencyTimeStamp", Sqlite::ColumnType::Integer);
table.addColumn("isInPrecompiledHeader", Sqlite::ColumnType::Integer);
table.initialize(database); table.initialize(database);
} }

View File

@@ -264,7 +264,7 @@ int ExpressionUnderCursor::startOfFunctionCall(const QTextCursor &cursor) const
break; break;
} else if (tk.is(T_LPAREN) || tk.is(T_LBRACE)) { } else if (tk.is(T_LPAREN) || tk.is(T_LBRACE)) {
return scanner.startPosition() + tk.utf16charsBegin(); return scanner.startPosition() + tk.utf16charsBegin();
} else if (tk.is(T_RPAREN)) { } else if (tk.is(T_RPAREN) || tk.is(T_RBRACE)) {
int matchingBrace = scanner.startOfMatchingBrace(index); int matchingBrace = scanner.startOfMatchingBrace(index);
if (matchingBrace == index) // If no matching brace found if (matchingBrace == index) // If no matching brace found

View File

@@ -31,9 +31,27 @@ for(l, SUBDIRS) {
} }
SUBDIRS += \ SUBDIRS += \
utils/process_stub.pro \ utils/process_stub.pro
3rdparty/syntax-highlighting \
3rdparty/syntax-highlighting/data isEmpty(KSYNTAXHIGHLIGHTING_LIB_DIR): KSYNTAXHIGHLIGHTING_LIB_DIR=$$(KSYNTAXHIGHLIGHTING_LIB_DIR)
!isEmpty(KSYNTAXHIGHLIGHTING_LIB_DIR) {
# enable short information message
KSYNTAX_WARN_ON = 1
}
include(../shared/syntax/syntax_shared.pri)
isEmpty(KSYNTAXHIGHLIGHTING_LIB_DIR) {
SUBDIRS += \
3rdparty/syntax-highlighting \
3rdparty/syntax-highlighting/data
equals(KSYNTAX_WARN_ON, 1) {
message("Either KSYNTAXHIGHLIGHTING_LIB_DIR does not exist or include path could not be deduced.")
unset(KSYNTAX_WARN_ON)
}
} else {
message("Using KSyntaxHighlighting provided at $${KSYNTAXHIGHLIGHTING_LIB_DIR}.")
}
win32:SUBDIRS += utils/process_ctrlc_stub.pro win32:SUBDIRS += utils/process_ctrlc_stub.pro

View File

@@ -748,8 +748,8 @@ void Check::endVisit(UiObjectInitializer *)
{ {
m_propertyStack.pop(); m_propertyStack.pop();
m_typeStack.pop(); m_typeStack.pop();
UiObjectDefinition *objectDenition = cast<UiObjectDefinition *>(parent()); UiObjectDefinition *objectDefinition = cast<UiObjectDefinition *>(parent());
if (objectDenition && objectDenition->qualifiedTypeNameId->name == "Component") if (objectDefinition && objectDefinition->qualifiedTypeNameId->name == "Component")
m_idStack.pop(); m_idStack.pop();
UiObjectBinding *objectBinding = cast<UiObjectBinding *>(parent()); UiObjectBinding *objectBinding = cast<UiObjectBinding *>(parent());
if (objectBinding && objectBinding->qualifiedTypeNameId->name == "Component") if (objectBinding && objectBinding->qualifiedTypeNameId->name == "Component")

View File

@@ -69,7 +69,7 @@ SshRemoteProcess::SshRemoteProcess(const QByteArray &command, const QStringList
connect(this, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this] { connect(this, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, [this] {
QString error; QString error;
if (exitStatus() == QProcess::CrashExit) if (exitStatus() == QProcess::CrashExit)
error = tr("The ssh binary crashed: %1").arg(errorString()); error = tr("The ssh process crashed: %1").arg(errorString());
else if (exitCode() == 255) else if (exitCode() == 255)
error = tr("Remote process crashed."); error = tr("Remote process crashed.");
emit done(error); emit done(error);

View File

@@ -311,9 +311,10 @@ QString FileUtils::normalizePathName(const QString &name)
if (FAILED(hr)) if (FAILED(hr))
return name; return name;
TCHAR buffer[MAX_PATH]; TCHAR buffer[MAX_PATH];
if (!SHGetPathFromIDList(file, buffer)) const bool success = SHGetPathFromIDList(file, buffer);
return name; ILFree(file);
return QDir::fromNativeSeparators(QString::fromUtf16(reinterpret_cast<const ushort *>(buffer))); return success ? QDir::fromNativeSeparators(QString::fromUtf16(reinterpret_cast<const ushort *>(buffer)))
: name;
#elif defined(Q_OS_OSX) #elif defined(Q_OS_OSX)
return Internal::normalizePathName(name); return Internal::normalizePathName(name);
#else // do not try to handle case-insensitive file systems on Linux #else // do not try to handle case-insensitive file systems on Linux

View File

@@ -63,9 +63,9 @@ QVariant Utils::JsonTreeItem::data(int column, int role) const
if (column == 2) if (column == 2)
return typeName(m_value.type()); return typeName(m_value.type());
if (m_value.isObject()) if (m_value.isObject())
return QString('[' + QString::number(m_value.toObject().size()) + ' ' + tr("Items") + ']'); return QString('[' + tr("%n Items", nullptr, m_value.toObject().size()) + ']');
if (m_value.isArray()) if (m_value.isArray())
return QString('[' + QString::number(m_value.toArray().size()) + ' ' + tr("Items") + ']'); return QString('[' + tr("%n Items", nullptr, m_value.toArray().size()) + ']');
return m_value.toVariant(); return m_value.toVariant();
} }

View File

@@ -171,7 +171,8 @@ LineColumn utf16LineColumn(const QByteArray &utf8Buffer, int utf8Offset)
lineColumn.line = static_cast<int>( lineColumn.line = static_cast<int>(
std::count(utf8Buffer.begin(), utf8Buffer.begin() + utf8Offset, '\n')) std::count(utf8Buffer.begin(), utf8Buffer.begin() + utf8Offset, '\n'))
+ 1; + 1;
const int startOfLineOffset = utf8Buffer.lastIndexOf('\n', utf8Offset - 1) + 1; const int startOfLineOffset = utf8Offset ? (utf8Buffer.lastIndexOf('\n', utf8Offset - 1) + 1)
: 0;
lineColumn.column = QString::fromUtf8( lineColumn.column = QString::fromUtf8(
utf8Buffer.mid(startOfLineOffset, utf8Offset - startOfLineOffset)) utf8Buffer.mid(startOfLineOffset, utf8Offset - startOfLineOffset))
.length() .length()
@@ -181,7 +182,9 @@ LineColumn utf16LineColumn(const QByteArray &utf8Buffer, int utf8Offset)
QString utf16LineTextInUtf8Buffer(const QByteArray &utf8Buffer, int currentUtf8Offset) QString utf16LineTextInUtf8Buffer(const QByteArray &utf8Buffer, int currentUtf8Offset)
{ {
const int lineStartUtf8Offset = utf8Buffer.lastIndexOf('\n', currentUtf8Offset - 1) + 1; const int lineStartUtf8Offset = currentUtf8Offset
? (utf8Buffer.lastIndexOf('\n', currentUtf8Offset - 1) + 1)
: 0;
const int lineEndUtf8Offset = utf8Buffer.indexOf('\n', currentUtf8Offset); const int lineEndUtf8Offset = utf8Buffer.indexOf('\n', currentUtf8Offset);
return QString::fromUtf8( return QString::fromUtf8(
utf8Buffer.mid(lineStartUtf8Offset, lineEndUtf8Offset - lineStartUtf8Offset)); utf8Buffer.mid(lineStartUtf8Offset, lineEndUtf8Offset - lineStartUtf8Offset));

View File

@@ -101,7 +101,7 @@ public:
setSummaryText(displayName()); setSummaryText(displayName());
auto uninstallPreviousPackage = new QCheckBox(this); auto uninstallPreviousPackage = new QCheckBox(this);
uninstallPreviousPackage->setText(tr("Uninstall previous package")); uninstallPreviousPackage->setText(AndroidDeployQtStep::tr("Uninstall previous package"));
uninstallPreviousPackage->setChecked(step->uninstallPreviousPackage() > AndroidDeployQtStep::Keep); uninstallPreviousPackage->setChecked(step->uninstallPreviousPackage() > AndroidDeployQtStep::Keep);
uninstallPreviousPackage->setEnabled(step->uninstallPreviousPackage() != AndroidDeployQtStep::ForceUnintall); uninstallPreviousPackage->setEnabled(step->uninstallPreviousPackage() != AndroidDeployQtStep::ForceUnintall);

View File

@@ -68,13 +68,12 @@ void ClangCodeModelPlugin::generateCompilationDB() {
using namespace CppTools; using namespace CppTools;
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject(); ProjectExplorer::Project *project = ProjectExplorer::SessionManager::startupProject();
if (!project) if (!project || !project->activeTarget())
return; return;
m_generatorWatcher.setFuture(QtConcurrent::run( m_generatorWatcher.setFuture(
&Utils::generateCompilationDB, QtConcurrent::run(&Utils::generateCompilationDB,
project->projectDirectory(), CppModelManager::instance()->projectInfo(project)));
CppModelManager::instance()->projectInfo(project)));
} }
static bool isDBGenerationEnabled(ProjectExplorer::Project *project) static bool isDBGenerationEnabled(ProjectExplorer::Project *project)

View File

@@ -214,6 +214,9 @@ void ClangCompletionAssistProcessor::handleAvailableCompletions(const CodeComple
setAsyncProposalAvailable(createFunctionHintProposal(completions)); setAsyncProposalAvailable(createFunctionHintProposal(completions));
return; return;
} }
if (!m_fallbackToNormalCompletion)
return;
// else: Proceed with a normal completion in case: // else: Proceed with a normal completion in case:
// 1) it was not a function call, but e.g. a function declaration like "void f(" // 1) it was not a function call, but e.g. a function declaration like "void f("
// 2) '{' meant not a constructor call. // 2) '{' meant not a constructor call.
@@ -286,6 +289,14 @@ static QByteArray modifyInput(QTextDocument *doc, int endOfExpression) {
return modifiedInput; return modifiedInput;
} }
static QChar lastPrecedingNonWhitespaceChar(const ClangCompletionAssistInterface *interface)
{
int pos = interface->position();
while (pos >= 0 && interface->characterAt(pos).isSpace())
--pos;
return pos >= 0 ? interface->characterAt(pos) : QChar::Null;
}
IAssistProposal *ClangCompletionAssistProcessor::startCompletionHelper() IAssistProposal *ClangCompletionAssistProcessor::startCompletionHelper()
{ {
ClangCompletionContextAnalyzer analyzer(m_interface.data(), m_interface->languageFeatures()); ClangCompletionContextAnalyzer analyzer(m_interface.data(), m_interface->languageFeatures());
@@ -323,6 +334,8 @@ IAssistProposal *ClangCompletionAssistProcessor::startCompletionHelper()
} }
case ClangCompletionContextAnalyzer::PassThroughToLibClangAfterLeftParen: { case ClangCompletionContextAnalyzer::PassThroughToLibClangAfterLeftParen: {
m_sentRequestType = FunctionHintCompletion; m_sentRequestType = FunctionHintCompletion;
if (lastPrecedingNonWhitespaceChar(m_interface.data()) == ',')
m_fallbackToNormalCompletion = false;
m_requestSent = sendCompletionRequest(analyzer.positionForClang(), QByteArray(), m_requestSent = sendCompletionRequest(analyzer.positionForClang(), QByteArray(),
analyzer.functionNameStart()); analyzer.functionNameStart());
break; break;

View File

@@ -97,6 +97,7 @@ private:
CompletionRequestType m_sentRequestType = NormalCompletion; CompletionRequestType m_sentRequestType = NormalCompletion;
bool m_requestSent = false; bool m_requestSent = false;
bool m_addSnippets = false; // For type == Type::NormalCompletion bool m_addSnippets = false; // For type == Type::NormalCompletion
bool m_fallbackToNormalCompletion = true;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -110,6 +110,8 @@ int ClangCompletionContextAnalyzer::startOfFunctionCall(int endOfOperator) const
functionNameSelector.setPosition(functionNameStart); functionNameSelector.setPosition(functionNameStart);
functionNameSelector.setPosition(index, QTextCursor::KeepAnchor); functionNameSelector.setPosition(index, QTextCursor::KeepAnchor);
const QString functionName = functionNameSelector.selectedText().trimmed(); const QString functionName = functionNameSelector.selectedText().trimmed();
if (functionName.isEmpty() && m_completionOperator == T_LBRACE)
return endOfOperator;
return functionName.isEmpty() ? -1 : functionNameStart; return functionName.isEmpty() ? -1 : functionNameStart;
} }
@@ -139,7 +141,10 @@ void ClangCompletionContextAnalyzer::handleCommaInFunctionCall()
const int start = expressionUnderCursor.startOfFunctionCall(textCursor); const int start = expressionUnderCursor.startOfFunctionCall(textCursor);
m_positionEndOfExpression = start; m_positionEndOfExpression = start;
m_positionForProposal = start + 1; // After '(' of function call m_positionForProposal = start + 1; // After '(' of function call
m_completionOperator = T_LPAREN; if (m_interface->characterAt(start) == '(')
m_completionOperator = T_LPAREN;
else
m_completionOperator = T_LBRACE;
} }
} }

View File

@@ -34,12 +34,13 @@
#include <coreplugin/idocument.h> #include <coreplugin/idocument.h>
#include <cpptools/baseeditordocumentparser.h> #include <cpptools/baseeditordocumentparser.h>
#include <cpptools/compileroptionsbuilder.h> #include <cpptools/compileroptionsbuilder.h>
#include <cpptools/cppcodemodelsettings.h>
#include <cpptools/cppmodelmanager.h> #include <cpptools/cppmodelmanager.h>
#include <cpptools/cpptoolsreuse.h>
#include <cpptools/editordocumenthandle.h> #include <cpptools/editordocumenthandle.h>
#include <cpptools/projectpart.h> #include <cpptools/projectpart.h>
#include <cpptools/cppcodemodelsettings.h>
#include <cpptools/cpptoolsreuse.h>
#include <projectexplorer/buildconfiguration.h> #include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
@@ -300,12 +301,24 @@ QString diagnosticCategoryPrefixRemoved(const QString &text)
return text; return text;
} }
static ::Utils::FileName buildDirectory(const CppTools::ProjectPart &projectPart) static ::Utils::FileName compilerPath(const CppTools::ProjectPart &projectPart)
{ {
ProjectExplorer::Target *target = projectPart.project->activeTarget(); ProjectExplorer::Target *target = projectPart.project->activeTarget();
if (!target) if (!target)
return ::Utils::FileName(); return ::Utils::FileName();
ProjectExplorer::ToolChain *toolchain = ProjectExplorer::ToolChainKitAspect::toolChain(
target->kit(), ProjectExplorer::Constants::CXX_LANGUAGE_ID);
return toolchain->compilerCommand();
}
static ::Utils::FileName buildDirectory(const ProjectExplorer::Project &project)
{
ProjectExplorer::Target *target = project.activeTarget();
if (!target)
return ::Utils::FileName();
ProjectExplorer::BuildConfiguration *buildConfig = target->activeBuildConfiguration(); ProjectExplorer::BuildConfiguration *buildConfig = target->activeBuildConfiguration();
if (!buildConfig) if (!buildConfig)
return ::Utils::FileName(); return ::Utils::FileName();
@@ -313,42 +326,84 @@ static ::Utils::FileName buildDirectory(const CppTools::ProjectPart &projectPart
return buildConfig->buildDirectory(); return buildConfig->buildDirectory();
} }
static QJsonObject createFileObject(CompilerOptionsBuilder &optionsBuilder, static QStringList projectPartArguments(const ProjectPart &projectPart)
const ProjectFile &projFile,
const ::Utils::FileName &buildDir)
{ {
const ProjectFile::Kind kind = ProjectFile::classify(projFile.path); QStringList args;
optionsBuilder.updateFileLanguage(kind); args << compilerPath(projectPart).toString();
args << "-c";
if (projectPart.toolchainType != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) {
args << "--target=" + projectPart.toolChainTargetTriple;
args << (projectPart.toolChainWordWidth == ProjectPart::WordWidth64Bit
? QLatin1String("-m64")
: QLatin1String("-m32"));
}
args << projectPart.compilerFlags;
for (const ProjectExplorer::HeaderPath &headerPath : projectPart.headerPaths) {
if (headerPath.type == ProjectExplorer::HeaderPathType::User) {
args << "-I" + headerPath.path;
} else if (headerPath.type == ProjectExplorer::HeaderPathType::System) {
args << (projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID
? "-I"
: "-isystem")
+ headerPath.path;
}
}
for (const ProjectExplorer::Macro &macro : projectPart.projectMacros) {
args.append(QString::fromUtf8(
macro.toKeyValue(macro.type == ProjectExplorer::MacroType::Define ? "-D" : "-U")));
}
return args;
}
static QJsonObject createFileObject(const ::Utils::FileName &buildDir,
const QStringList &arguments,
const ProjectPart &projectPart,
const ProjectFile &projFile)
{
QJsonObject fileObject; QJsonObject fileObject;
fileObject["file"] = projFile.path; fileObject["file"] = projFile.path;
QJsonArray args = QJsonArray::fromStringList(optionsBuilder.options()); QJsonArray args = QJsonArray::fromStringList(arguments);
args.prepend(kind == ProjectFile::CXXSource ? "clang++" : "clang");
const ProjectFile::Kind kind = ProjectFile::classify(projFile.path);
if (projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID
|| projectPart.toolchainType == ProjectExplorer::Constants::CLANG_CL_TOOLCHAIN_TYPEID) {
if (ProjectFile::isC(kind))
args.append("/TC");
else if (ProjectFile::isCxx(kind))
args.append("/TP");
} else {
QStringList langOption
= createLanguageOptionGcc(kind,
projectPart.languageExtensions
& ::Utils::LanguageExtension::ObjectiveC);
for (const QString &langOptionPart : langOption)
args.append(langOptionPart);
}
args.append(QDir::toNativeSeparators(projFile.path)); args.append(QDir::toNativeSeparators(projFile.path));
fileObject["arguments"] = args; fileObject["arguments"] = args;
fileObject["directory"] = buildDir.toString(); fileObject["directory"] = buildDir.toString();
return fileObject; return fileObject;
} }
void generateCompilationDB(::Utils::FileName projectDir, CppTools::ProjectInfo projectInfo) void generateCompilationDB(CppTools::ProjectInfo projectInfo)
{ {
QFile compileCommandsFile(projectDir.toString() + "/compile_commands.json"); const ::Utils::FileName buildDir = buildDirectory(*projectInfo.project());
QTC_ASSERT(!buildDir.isEmpty(), return;);
QDir dir(buildDir.toString());
if (!dir.exists())
dir.mkpath(dir.path());
QFile compileCommandsFile(buildDir.toString() + "/compile_commands.json");
const bool fileOpened = compileCommandsFile.open(QIODevice::WriteOnly | QIODevice::Truncate); const bool fileOpened = compileCommandsFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
if (!fileOpened) if (!fileOpened)
return; return;
compileCommandsFile.write("["); compileCommandsFile.write("[");
for (ProjectPart::Ptr projectPart : projectInfo.projectParts()) { for (ProjectPart::Ptr projectPart : projectInfo.projectParts()) {
const ::Utils::FileName buildDir = buildDirectory(*projectPart); const QStringList args = projectPartArguments(*projectPart);
CompilerOptionsBuilder optionsBuilder(*projectPart,
UseSystemHeader::No,
UseTweakedHeaderPaths::No);
optionsBuilder.build(CppTools::ProjectFile::Unclassified,
CppTools::UsePrecompiledHeaders::No);
for (const ProjectFile &projFile : projectPart->files) { for (const ProjectFile &projFile : projectPart->files) {
const QJsonObject json = createFileObject(optionsBuilder, projFile, buildDir); const QJsonObject json = createFileObject(buildDir, args, *projectPart, projFile);
if (compileCommandsFile.size() > 1) if (compileCommandsFile.size() > 1)
compileCommandsFile.write(","); compileCommandsFile.write(",");
compileCommandsFile.write('\n' + QJsonDocument(json).toJson().trimmed()); compileCommandsFile.write('\n' + QJsonDocument(json).toJson().trimmed());

View File

@@ -70,7 +70,7 @@ QString diagnosticCategoryPrefixRemoved(const QString &text);
::Utils::CodeModelIcon::Type iconTypeForToken(const ClangBackEnd::TokenInfoContainer &token); ::Utils::CodeModelIcon::Type iconTypeForToken(const ClangBackEnd::TokenInfoContainer &token);
void generateCompilationDB(::Utils::FileName projectDir, CppTools::ProjectInfo projectInfo); void generateCompilationDB(CppTools::ProjectInfo projectInfo);
class DiagnosticTextInfo class DiagnosticTextInfo
{ {

View File

@@ -2,7 +2,7 @@
\"Name\" : \"ClangFormat\", \"Name\" : \"ClangFormat\",
\"Version\" : \"$$QTCREATOR_VERSION\", \"Version\" : \"$$QTCREATOR_VERSION\",
\"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\", \"CompatVersion\" : \"$$QTCREATOR_COMPAT_VERSION\",
\"Experimental\" : true, \"DisabledByDefault\" : true,
\"Vendor\" : \"The Qt Company Ltd\", \"Vendor\" : \"The Qt Company Ltd\",
\"Copyright\" : \"(C) $$QTCREATOR_COPYRIGHT_YEAR The Qt Company Ltd\", \"Copyright\" : \"(C) $$QTCREATOR_COPYRIGHT_YEAR The Qt Company Ltd\",
\"License\" : [ \"Commercial Usage\", \"License\" : [ \"Commercial Usage\",

View File

@@ -29,9 +29,10 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/textutils.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/textutils.h>
#include <QDebug>
#include <QTextDocument> #include <QTextDocument>
namespace ClangFormat { namespace ClangFormat {
@@ -126,9 +127,85 @@ void trimRHSWhitespace(const QTextBlock &block)
cursor.endEditBlock(); cursor.endEditBlock();
} }
QTextBlock reverseFindLastEmptyBlock(QTextBlock start)
{
if (start.position() > 0) {
start = start.previous();
while (start.position() > 0 && start.text().trimmed().isEmpty())
start = start.previous();
if (!start.text().trimmed().isEmpty())
start = start.next();
}
return start;
}
enum class CharacterContext { AfterComma, LastAfterComma, NewStatement, Continuation, Unknown };
QChar findFirstNonWhitespaceCharacter(const QTextBlock &currentBlock)
{
const QTextDocument *doc = currentBlock.document();
int currentPos = currentBlock.position();
while (currentPos < doc->characterCount() && doc->characterAt(currentPos).isSpace())
++currentPos;
return currentPos < doc->characterCount() ? doc->characterAt(currentPos) : QChar::Null;
}
CharacterContext characterContext(const QTextBlock &currentBlock,
const QTextBlock &previousNonEmptyBlock)
{
const QString prevLineText = previousNonEmptyBlock.text().trimmed();
const QChar firstNonWhitespaceChar = findFirstNonWhitespaceCharacter(currentBlock);
if (prevLineText.endsWith(',')) {
// We don't need to add comma in case it's the last argument.
if (firstNonWhitespaceChar == '}' || firstNonWhitespaceChar == ')')
return CharacterContext::LastAfterComma;
return CharacterContext::AfterComma;
}
if (prevLineText.endsWith(';') || prevLineText.endsWith('{') || prevLineText.endsWith('}')
|| firstNonWhitespaceChar == QChar::Null) {
return CharacterContext::NewStatement;
}
return CharacterContext::Continuation;
}
bool nextBlockExistsAndEmpty(const QTextBlock &currentBlock)
{
QTextBlock nextBlock = currentBlock.next();
if (!nextBlock.isValid() || nextBlock.position() == currentBlock.position())
return false;
return nextBlock.text().trimmed().isEmpty();
}
QByteArray dummyTextForContext(CharacterContext context, bool closingBraceBlock)
{
if (closingBraceBlock
&& (context == CharacterContext::NewStatement
|| context == CharacterContext::Continuation)) {
return QByteArray();
}
switch (context) {
case CharacterContext::Unknown:
QTC_ASSERT(false, return "";);
case CharacterContext::AfterComma:
return "a,";
case CharacterContext::NewStatement:
return "a;";
case CharacterContext::Continuation:
case CharacterContext::LastAfterComma:
return "& a &";
}
}
// Add extra text in case of the empty line or the line starting with ')'. // Add extra text in case of the empty line or the line starting with ')'.
// Track such extra pieces of text in isInsideModifiedLine(). // Track such extra pieces of text in isInsideModifiedLine().
int forceIndentWithExtraText(QByteArray &buffer, const QTextBlock &block, bool secondTry) int forceIndentWithExtraText(QByteArray &buffer,
CharacterContext &charContext,
const QTextBlock &block,
bool secondTry)
{ {
const QString blockText = block.text(); const QString blockText = block.text();
int firstNonWhitespace = Utils::indexOf(blockText, int firstNonWhitespace = Utils::indexOf(blockText,
@@ -143,26 +220,33 @@ int forceIndentWithExtraText(QByteArray &buffer, const QTextBlock &block, bool s
const bool closingParenBlock = firstNonWhitespace >= 0 const bool closingParenBlock = firstNonWhitespace >= 0
&& blockText.at(firstNonWhitespace) == ')'; && blockText.at(firstNonWhitespace) == ')';
const bool closingBraceBlock = firstNonWhitespace >= 0
&& blockText.at(firstNonWhitespace) == '}';
int extraLength = 0; int extraLength = 0;
if (firstNonWhitespace < 0 || closingParenBlock) { QByteArray dummyText;
//This extra text works for the most cases. if (firstNonWhitespace < 0 && charContext != CharacterContext::Unknown
QByteArray dummyText("a;a;"); && nextBlockExistsAndEmpty(block)) {
// If the next line is also empty it's safer to use a comment line.
dummyText = "//";
} else if (firstNonWhitespace < 0 || closingParenBlock || closingBraceBlock) {
if (charContext == CharacterContext::LastAfterComma) {
charContext = CharacterContext::AfterComma;
} else if (charContext == CharacterContext::Unknown || firstNonWhitespace >= 0) {
QTextBlock lastBlock = reverseFindLastEmptyBlock(block);
if (lastBlock.position() > 0)
lastBlock = lastBlock.previous();
// Search for previous character // If we don't know yet the dummy text, let's guess it and use for this line and before.
QTextBlock prevBlock = block.previous(); charContext = characterContext(block, lastBlock);
bool prevBlockIsEmpty = prevBlock.position() > 0 && prevBlock.text().trimmed().isEmpty();
while (prevBlockIsEmpty) {
prevBlock = prevBlock.previous();
prevBlockIsEmpty = prevBlock.position() > 0 && prevBlock.text().trimmed().isEmpty();
} }
if (closingParenBlock || prevBlock.text().endsWith(','))
dummyText = "&& a";
buffer.insert(utf8Offset, dummyText); dummyText = dummyTextForContext(charContext, closingBraceBlock);
extraLength += dummyText.length();
} }
buffer.insert(utf8Offset, dummyText);
extraLength += dummyText.length();
if (secondTry) { if (secondTry) {
int nextLinePos = buffer.indexOf('\n', utf8Offset); int nextLinePos = buffer.indexOf('\n', utf8Offset);
if (nextLinePos < 0) if (nextLinePos < 0)
@@ -170,7 +254,7 @@ int forceIndentWithExtraText(QByteArray &buffer, const QTextBlock &block, bool s
if (nextLinePos > 0) { if (nextLinePos > 0) {
// If first try was not successful try to put ')' in the end of the line to close possibly // If first try was not successful try to put ')' in the end of the line to close possibly
// unclosed parentheses. // unclosed parenthesis.
// TODO: Does it help to add different endings depending on the context? // TODO: Does it help to add different endings depending on the context?
buffer.insert(nextLinePos, ')'); buffer.insert(nextLinePos, ')');
extraLength += 1; extraLength += 1;
@@ -300,18 +384,6 @@ bool doNotIndentInContext(QTextDocument *doc, int pos)
return false; return false;
} }
QTextBlock reverseFindLastEmptyBlock(QTextBlock start)
{
if (start.position() > 0) {
start = start.previous();
while (start.position() > 0 && start.text().trimmed().isEmpty())
start = start.previous();
if (!start.text().trimmed().isEmpty())
start = start.next();
}
return start;
}
int formattingRangeStart(const QTextBlock &currentBlock, int formattingRangeStart(const QTextBlock &currentBlock,
const QByteArray &buffer, const QByteArray &buffer,
int documentRevision) int documentRevision)
@@ -355,23 +427,14 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer
rangeStart = formattingRangeStart(startBlock, buffer, lastSaveRevision()); rangeStart = formattingRangeStart(startBlock, buffer, lastSaveRevision());
adjustFormatStyleForLineBreak(style, replacementsToKeep); adjustFormatStyleForLineBreak(style, replacementsToKeep);
if (typedChar == QChar::Null) { if (replacementsToKeep == ReplacementsToKeep::OnlyIndent) {
if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore) { CharacterContext currentCharContext = CharacterContext::Unknown;
if (utf8Offset > 0) { // Iterate backwards to reuse the same dummy text for all empty lines.
buffer.insert(utf8Offset - 1, " //"); for (int index = endBlock.blockNumber(); index >= startBlock.blockNumber(); --index) {
utf8Offset += 3;
}
utf8Length += forceIndentWithExtraText(buffer, utf8Length += forceIndentWithExtraText(buffer,
cursorPositionInEditor < 0 currentCharContext,
? endBlock m_doc->findBlockByNumber(index),
: m_doc->findBlock(cursorPositionInEditor),
secondTry); secondTry);
} else {
for (int index = startBlock.blockNumber(); index <= endBlock.blockNumber(); ++index) {
utf8Length += forceIndentWithExtraText(buffer,
m_doc->findBlockByNumber(index),
secondTry);
}
} }
} }
@@ -432,9 +495,24 @@ TextEditor::Replacements ClangFormatBaseIndenter::format(
static_cast<unsigned int>(utf8RangeLength)); static_cast<unsigned int>(utf8RangeLength));
} }
clang::format::FormatStyle style = styleForFile();
const std::string assumedFileName = m_fileName.toString().toStdString();
clang::tooling::Replacements clangReplacements = clang::format::sortIncludes(style,
buffer.data(),
ranges,
assumedFileName);
auto changedCode = clang::tooling::applyAllReplacements(buffer.data(), clangReplacements);
QTC_ASSERT(changedCode, {
qDebug() << QString::fromStdString(llvm::toString(changedCode.takeError()));
return TextEditor::Replacements();
});
ranges = clang::tooling::calculateRangesAfterReplacements(clangReplacements, ranges);
clang::format::FormattingAttemptStatus status; clang::format::FormattingAttemptStatus status;
const clang::tooling::Replacements clangReplacements const clang::tooling::Replacements formatReplacements
= reformat(styleForFile(), buffer.data(), ranges, m_fileName.toString().toStdString(), &status); = reformat(style, *changedCode, ranges, m_fileName.toString().toStdString(), &status);
clangReplacements = clangReplacements.merge(formatReplacements);
const TextEditor::Replacements toReplace = utf16Replacements(m_doc, buffer, clangReplacements); const TextEditor::Replacements toReplace = utf16Replacements(m_doc, buffer, clangReplacements);
applyReplacements(m_doc, toReplace); applyReplacements(m_doc, toReplace);
@@ -443,7 +521,6 @@ TextEditor::Replacements ClangFormatBaseIndenter::format(
TextEditor::Replacements ClangFormatBaseIndenter::indentsFor(QTextBlock startBlock, TextEditor::Replacements ClangFormatBaseIndenter::indentsFor(QTextBlock startBlock,
const QTextBlock &endBlock, const QTextBlock &endBlock,
const QByteArray &buffer,
const QChar &typedChar, const QChar &typedChar,
int cursorPositionInEditor) int cursorPositionInEditor)
{ {
@@ -461,10 +538,12 @@ TextEditor::Replacements ClangFormatBaseIndenter::indentsFor(QTextBlock startBlo
cursorPositionInEditor += startBlock.position() - startBlockPosition; cursorPositionInEditor += startBlock.position() - startBlockPosition;
} }
const QByteArray buffer = m_doc->toPlainText().toUtf8();
ReplacementsToKeep replacementsToKeep = ReplacementsToKeep::OnlyIndent; ReplacementsToKeep replacementsToKeep = ReplacementsToKeep::OnlyIndent;
if (formatWhileTyping() if (formatWhileTyping()
&& (cursorPositionInEditor == -1 || cursorPositionInEditor >= startBlockPosition) && (cursorPositionInEditor == -1 || cursorPositionInEditor >= startBlockPosition)
&& (typedChar == QChar::Null || typedChar == ';' || typedChar == '}')) { && (typedChar == ';' || typedChar == '}')) {
// Format before current position only in case the cursor is inside the indented block. // Format before current position only in case the cursor is inside the indented block.
// So if cursor position is less then the block position then the current line is before // So if cursor position is less then the block position then the current line is before
// the indented block - don't trigger extra formatting in this case. // the indented block - don't trigger extra formatting in this case.
@@ -487,9 +566,7 @@ void ClangFormatBaseIndenter::indentBlocks(const QTextBlock &startBlock,
const QChar &typedChar, const QChar &typedChar,
int cursorPositionInEditor) int cursorPositionInEditor)
{ {
const QByteArray buffer = m_doc->toPlainText().toUtf8(); applyReplacements(m_doc, indentsFor(startBlock, endBlock, typedChar, cursorPositionInEditor));
applyReplacements(m_doc,
indentsFor(startBlock, endBlock, buffer, typedChar, cursorPositionInEditor));
} }
void ClangFormatBaseIndenter::indent(const QTextCursor &cursor, void ClangFormatBaseIndenter::indent(const QTextCursor &cursor,
@@ -533,15 +610,14 @@ int ClangFormatBaseIndenter::indentFor(const QTextBlock &block,
const TextEditor::TabSettings & /*tabSettings*/, const TextEditor::TabSettings & /*tabSettings*/,
int cursorPositionInEditor) int cursorPositionInEditor)
{ {
const QByteArray buffer = m_doc->toPlainText().toUtf8();
TextEditor::Replacements toReplace = indentsFor(block, TextEditor::Replacements toReplace = indentsFor(block,
block, block,
buffer,
QChar::Null, QChar::Null,
cursorPositionInEditor); cursorPositionInEditor);
if (toReplace.empty()) if (toReplace.empty())
return -1; return -1;
const QByteArray buffer = m_doc->toPlainText().toUtf8();
return indentationForBlock(toReplace, buffer, block); return indentationForBlock(toReplace, buffer, block);
} }
@@ -553,13 +629,12 @@ TextEditor::IndentationForBlock ClangFormatBaseIndenter::indentationForBlocks(
TextEditor::IndentationForBlock ret; TextEditor::IndentationForBlock ret;
if (blocks.isEmpty()) if (blocks.isEmpty())
return ret; return ret;
const QByteArray buffer = m_doc->toPlainText().toUtf8();
TextEditor::Replacements toReplace = indentsFor(blocks.front(), TextEditor::Replacements toReplace = indentsFor(blocks.front(),
blocks.back(), blocks.back(),
buffer,
QChar::Null, QChar::Null,
cursorPositionInEditor); cursorPositionInEditor);
const QByteArray buffer = m_doc->toPlainText().toUtf8();
for (const QTextBlock &block : blocks) for (const QTextBlock &block : blocks)
ret.insert(block.blockNumber(), indentationForBlock(toReplace, buffer, block)); ret.insert(block.blockNumber(), indentationForBlock(toReplace, buffer, block));
return ret; return ret;

View File

@@ -81,7 +81,6 @@ private:
int cursorPositionInEditor); int cursorPositionInEditor);
TextEditor::Replacements indentsFor(QTextBlock startBlock, TextEditor::Replacements indentsFor(QTextBlock startBlock,
const QTextBlock &endBlock, const QTextBlock &endBlock,
const QByteArray &buffer,
const QChar &typedChar, const QChar &typedChar,
int cursorPositionInEditor); int cursorPositionInEditor);
TextEditor::Replacements replacements(QByteArray buffer, TextEditor::Replacements replacements(QByteArray buffer,

View File

@@ -59,6 +59,24 @@ ClangFormatConfigWidget::ClangFormatConfigWidget(ProjectExplorer::Project *proje
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
m_preview = new TextEditor::SnippetEditorWidget(this);
m_ui->horizontalLayout_2->addWidget(m_preview);
if (m_project) {
m_ui->applyButton->show();
hideGlobalCheckboxes();
m_ui->overrideDefault->setChecked(
m_project->namedSettings(Constants::OVERRIDE_FILE_ID).toBool());
} else {
m_ui->applyButton->hide();
showGlobalCheckboxes();
m_ui->overrideDefault->setChecked(ClangFormatSettings::instance().overrideDefaultFile());
}
connect(m_ui->overrideDefault, &QCheckBox::toggled, this, [this](bool checked) {
if (checked)
createStyleFileIfNeeded(!m_project);
initialize();
});
initialize(); initialize();
} }
@@ -81,15 +99,19 @@ void ClangFormatConfigWidget::showGlobalCheckboxes()
m_ui->formatOnSave->show(); m_ui->formatOnSave->show();
} }
static bool projectConfigExists()
{
return Utils::FileName::fromString(Core::ICore::userResourcePath())
.appendPath("clang-format")
.appendPath(currentProjectUniqueId())
.appendPath((Constants::SETTINGS_FILE_NAME))
.exists();
}
void ClangFormatConfigWidget::initialize() void ClangFormatConfigWidget::initialize()
{ {
m_ui->projectHasClangFormat->show(); m_ui->projectHasClangFormat->hide();
m_ui->clangFormatOptionsTable->show();
m_ui->applyButton->show();
hideGlobalCheckboxes();
m_preview = new TextEditor::SnippetEditorWidget(this);
m_ui->horizontalLayout_2->addWidget(m_preview);
m_preview->setPlainText(QLatin1String(CppTools::Constants::DEFAULT_CODE_STYLE_SNIPPETS[0])); m_preview->setPlainText(QLatin1String(CppTools::Constants::DEFAULT_CODE_STYLE_SNIPPETS[0]));
m_preview->textDocument()->setIndenter(new ClangFormatIndenter(m_preview->document())); m_preview->textDocument()->setIndenter(new ClangFormatIndenter(m_preview->document()));
m_preview->textDocument()->setFontSettings(TextEditor::TextEditorSettings::fontSettings()); m_preview->textDocument()->setFontSettings(TextEditor::TextEditorSettings::fontSettings());
@@ -103,21 +125,15 @@ void ClangFormatConfigWidget::initialize()
if (lastItem->spacerItem()) if (lastItem->spacerItem())
m_ui->verticalLayout->removeItem(lastItem); m_ui->verticalLayout->removeItem(lastItem);
if (m_project if (!m_ui->overrideDefault->isChecked()) {
&& !m_project->projectDirectory().appendPath(Constants::SETTINGS_FILE_NAME).exists()) {
m_ui->projectHasClangFormat->setText(tr("No .clang-format file for the project."));
m_ui->clangFormatOptionsTable->hide(); m_ui->clangFormatOptionsTable->hide();
m_ui->applyButton->hide(); m_preview->hide();
m_ui->verticalLayout->addStretch(1); m_ui->verticalLayout->addStretch(1);
connect(m_ui->createFileButton, &QPushButton::clicked, this, [this]() {
createStyleFileIfNeeded(false);
initialize();
});
return; return;
} }
m_ui->createFileButton->hide(); m_ui->clangFormatOptionsTable->show();
m_preview->show();
Utils::FileName fileName; Utils::FileName fileName;
if (m_project) { if (m_project) {
@@ -126,19 +142,13 @@ void ClangFormatConfigWidget::initialize()
fileName = m_project->projectFilePath().appendPath("snippet.cpp"); fileName = m_project->projectFilePath().appendPath("snippet.cpp");
} else { } else {
const Project *currentProject = SessionManager::startupProject(); const Project *currentProject = SessionManager::startupProject();
if (!currentProject if (!currentProject || !projectConfigExists()) {
|| !currentProject->projectDirectory()
.appendPath(Constants::SETTINGS_FILE_NAME)
.exists()) {
m_ui->projectHasClangFormat->hide(); m_ui->projectHasClangFormat->hide();
} else { } else {
m_ui->projectHasClangFormat->setText( m_ui->projectHasClangFormat->setText(
tr("Current project has its own .clang-format file " tr("Current project has its own overridden .clang-format file "
"and can be configured in Projects > Code Style > C++.")); "and can be configured in Projects > Code Style > C++."));
} }
createStyleFileIfNeeded(true);
showGlobalCheckboxes();
m_ui->applyButton->hide();
fileName = Utils::FileName::fromString(Core::ICore::userResourcePath()) fileName = Utils::FileName::fromString(Core::ICore::userResourcePath())
.appendPath("snippet.cpp"); .appendPath("snippet.cpp");
} }
@@ -160,7 +170,7 @@ void ClangFormatConfigWidget::fillTable()
{ {
clang::format::FormatStyle style = m_project ? currentProjectStyle() : currentGlobalStyle(); clang::format::FormatStyle style = m_project ? currentProjectStyle() : currentGlobalStyle();
std::string configText = clang::format::configurationAsText(style); const std::string configText = clang::format::configurationAsText(style);
m_ui->clangFormatOptionsTable->setPlainText(QString::fromStdString(configText)); m_ui->clangFormatOptionsTable->setPlainText(QString::fromStdString(configText));
} }
@@ -168,13 +178,19 @@ ClangFormatConfigWidget::~ClangFormatConfigWidget() = default;
void ClangFormatConfigWidget::apply() void ClangFormatConfigWidget::apply()
{ {
ClangFormatSettings &settings = ClangFormatSettings::instance();
if (!m_project) { if (!m_project) {
ClangFormatSettings &settings = ClangFormatSettings::instance();
settings.setFormatCodeInsteadOfIndent(m_ui->formatAlways->isChecked()); settings.setFormatCodeInsteadOfIndent(m_ui->formatAlways->isChecked());
settings.setFormatWhileTyping(m_ui->formatWhileTyping->isChecked()); settings.setFormatWhileTyping(m_ui->formatWhileTyping->isChecked());
settings.setFormatOnSave(m_ui->formatOnSave->isChecked()); settings.setFormatOnSave(m_ui->formatOnSave->isChecked());
settings.write(); settings.setOverrideDefaultFile(m_ui->overrideDefault->isChecked());
} else {
m_project->setNamedSettings(Constants::OVERRIDE_FILE_ID, m_ui->overrideDefault->isChecked());
} }
settings.write();
if (!m_ui->overrideDefault->isChecked())
return;
const QString text = m_ui->clangFormatOptionsTable->toPlainText(); const QString text = m_ui->clangFormatOptionsTable->toPlainText();
clang::format::FormatStyle style; clang::format::FormatStyle style;
@@ -184,16 +200,18 @@ void ClangFormatConfigWidget::apply()
QMessageBox::warning(this, QMessageBox::warning(this,
tr("Error in ClangFormat configuration"), tr("Error in ClangFormat configuration"),
QString::fromStdString(error.message())); QString::fromStdString(error.message()));
fillTable(); if (m_ui->overrideDefault->isChecked()) {
updatePreview(); fillTable();
updatePreview();
}
return; return;
} }
QString filePath; QString filePath = Core::ICore::userResourcePath();
if (m_project) if (m_project)
filePath = m_project->projectDirectory().appendPath(Constants::SETTINGS_FILE_NAME).toString(); filePath += "/clang-format/" + currentProjectUniqueId();
else filePath += "/" + QLatin1String(Constants::SETTINGS_FILE_NAME);
filePath = Core::ICore::userResourcePath() + "/" + Constants::SETTINGS_FILE_NAME;
QFile file(filePath); QFile file(filePath);
if (!file.open(QFile::WriteOnly)) if (!file.open(QFile::WriteOnly))
return; return;
@@ -201,7 +219,8 @@ void ClangFormatConfigWidget::apply()
file.write(text.toUtf8()); file.write(text.toUtf8());
file.close(); file.close();
updatePreview(); if (m_ui->overrideDefault->isChecked())
updatePreview();
} }
} // namespace ClangFormat } // namespace ClangFormat

View File

@@ -54,6 +54,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="overrideDefault">
<property name="text">
<string>Override Clang Format configuration file</string>
</property>
</widget>
</item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<item> <item>
@@ -63,13 +70,6 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="createFileButton">
<property name="text">
<string>Create Clang Format Configuration File</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QPushButton" name="applyButton"> <widget class="QPushButton" name="applyButton">
<property name="text"> <property name="text">

View File

@@ -34,5 +34,7 @@ static const char SETTINGS_ID[] = "ClangFormat";
static const char FORMAT_CODE_INSTEAD_OF_INDENT_ID[] = "ClangFormat.FormatCodeInsteadOfIndent"; static const char FORMAT_CODE_INSTEAD_OF_INDENT_ID[] = "ClangFormat.FormatCodeInsteadOfIndent";
static const char FORMAT_WHILE_TYPING_ID[] = "ClangFormat.FormatWhileTyping"; static const char FORMAT_WHILE_TYPING_ID[] = "ClangFormat.FormatWhileTyping";
static const char FORMAT_CODE_ON_SAVE_ID[] = "ClangFormat.FormatCodeOnSave"; static const char FORMAT_CODE_ON_SAVE_ID[] = "ClangFormat.FormatCodeOnSave";
static const char OVERRIDE_FILE_ID[] = "ClangFormat.OverrideFile";
static const char OPEN_CURRENT_CONFIG_ID[] = "ClangFormat.OpenCurrentConfig";
} // namespace Constants } // namespace Constants
} // namespace ClangFormat } // namespace ClangFormat

View File

@@ -57,7 +57,7 @@ bool ClangFormatIndenter::formatWhileTyping() const
Utils::optional<TabSettings> ClangFormatIndenter::tabSettings() const Utils::optional<TabSettings> ClangFormatIndenter::tabSettings() const
{ {
FormatStyle style = currentProjectStyle(); FormatStyle style = styleForFile();
TabSettings tabSettings; TabSettings tabSettings;
switch (style.UseTab) { switch (style.UseTab) {

View File

@@ -26,16 +26,23 @@
#include "clangformatplugin.h" #include "clangformatplugin.h"
#include "clangformatconfigwidget.h" #include "clangformatconfigwidget.h"
#include "clangformatconstants.h"
#include "clangformatindenter.h" #include "clangformatindenter.h"
#include "clangformatutils.h"
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <coreplugin/icore.h> #include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/icontext.h>
#include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h> #include <coreplugin/actionmanager/command.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
#include <coreplugin/idocument.h>
#include <cppeditor/cppeditorconstants.h>
#include <cpptools/cppcodestylepreferencesfactory.h> #include <cpptools/cppcodestylepreferencesfactory.h>
#include <cpptools/cpptoolsconstants.h> #include <cpptools/cpptoolsconstants.h>
@@ -103,6 +110,48 @@ bool ClangFormatPlugin::initialize(const QStringList &arguments, QString *errorS
Q_UNUSED(errorString); Q_UNUSED(errorString);
#ifdef KEEP_LINE_BREAKS_FOR_NON_EMPTY_LINES_BACKPORTED #ifdef KEEP_LINE_BREAKS_FOR_NON_EMPTY_LINES_BACKPORTED
replaceCppCodeStyle(); replaceCppCodeStyle();
Core::ActionContainer *contextMenu = Core::ActionManager::actionContainer(
CppEditor::Constants::M_CONTEXT);
if (contextMenu) {
auto openClangFormatConfigAction
= new QAction(tr("Open Used .clang-format Configuration File"), this);
Core::Command *command
= Core::ActionManager::registerAction(openClangFormatConfigAction,
Constants::OPEN_CURRENT_CONFIG_ID);
contextMenu->addSeparator();
contextMenu->addAction(command);
if (Core::EditorManager::currentEditor()) {
const Core::IDocument *doc = Core::EditorManager::currentEditor()->document();
if (doc)
openClangFormatConfigAction->setData(doc->filePath().toString());
}
connect(openClangFormatConfigAction,
&QAction::triggered,
this,
[openClangFormatConfigAction]() {
const QString fileName = openClangFormatConfigAction->data().toString();
if (!fileName.isEmpty()) {
const QString clangFormatConfigPath = configForFile(
Utils::FileName::fromString(fileName));
Core::EditorManager::openEditor(clangFormatConfigPath);
}
});
connect(Core::EditorManager::instance(),
&Core::EditorManager::currentEditorChanged,
this,
[openClangFormatConfigAction](Core::IEditor *editor) {
if (!editor)
return;
const Core::IDocument *doc = editor->document();
if (doc)
openClangFormatConfigAction->setData(doc->filePath().toString());
});
}
#endif #endif
return true; return true;
} }

View File

@@ -46,6 +46,8 @@ ClangFormatSettings::ClangFormatSettings()
.toBool(); .toBool();
m_formatOnSave = settings->value(QLatin1String(Constants::FORMAT_CODE_ON_SAVE_ID), false) m_formatOnSave = settings->value(QLatin1String(Constants::FORMAT_CODE_ON_SAVE_ID), false)
.toBool(); .toBool();
m_overrideDefaultFile = settings->value(QLatin1String(Constants::OVERRIDE_FILE_ID), false)
.toBool();
settings->endGroup(); settings->endGroup();
} }
@@ -57,6 +59,7 @@ void ClangFormatSettings::write() const
m_formatCodeInsteadOfIndent); m_formatCodeInsteadOfIndent);
settings->setValue(QLatin1String(Constants::FORMAT_WHILE_TYPING_ID), m_formatWhileTyping); settings->setValue(QLatin1String(Constants::FORMAT_WHILE_TYPING_ID), m_formatWhileTyping);
settings->setValue(QLatin1String(Constants::FORMAT_CODE_ON_SAVE_ID), m_formatOnSave); settings->setValue(QLatin1String(Constants::FORMAT_CODE_ON_SAVE_ID), m_formatOnSave);
settings->setValue(QLatin1String(Constants::OVERRIDE_FILE_ID), m_overrideDefaultFile);
settings->endGroup(); settings->endGroup();
} }
@@ -90,4 +93,14 @@ bool ClangFormatSettings::formatOnSave() const
return m_formatOnSave; return m_formatOnSave;
} }
void ClangFormatSettings::setOverrideDefaultFile(bool enable)
{
m_overrideDefaultFile = enable;
}
bool ClangFormatSettings::overrideDefaultFile() const
{
return m_overrideDefaultFile;
}
} // namespace ClangFormat } // namespace ClangFormat

View File

@@ -25,6 +25,8 @@
#pragma once #pragma once
#include <QString>
namespace ClangFormat { namespace ClangFormat {
class ClangFormatSettings class ClangFormatSettings
@@ -43,10 +45,14 @@ public:
void setFormatOnSave(bool enable); void setFormatOnSave(bool enable);
bool formatOnSave() const; bool formatOnSave() const;
void setOverrideDefaultFile(bool enable);
bool overrideDefaultFile() const;
private: private:
bool m_formatCodeInsteadOfIndent = false; bool m_formatCodeInsteadOfIndent = false;
bool m_formatWhileTyping = false; bool m_formatWhileTyping = false;
bool m_formatOnSave = false; bool m_formatOnSave = false;
bool m_overrideDefaultFile = false;
}; };
} // namespace ClangFormat } // namespace ClangFormat

View File

@@ -26,6 +26,7 @@
#include "clangformatutils.h" #include "clangformatutils.h"
#include "clangformatconstants.h" #include "clangformatconstants.h"
#include "clangformatsettings.h"
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <cpptools/cppcodestylesettings.h> #include <cpptools/cppcodestylesettings.h>
@@ -33,6 +34,8 @@
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
#include <projectexplorer/session.h> #include <projectexplorer/session.h>
#include <QCryptographicHash>
using namespace clang; using namespace clang;
using namespace format; using namespace format;
using namespace llvm; using namespace llvm;
@@ -42,6 +45,104 @@ using namespace TextEditor;
namespace ClangFormat { namespace ClangFormat {
static clang::format::FormatStyle qtcStyle()
{
clang::format::FormatStyle style = getLLVMStyle();
style.Language = FormatStyle::LK_Cpp;
style.AccessModifierOffset = -4;
style.AlignAfterOpenBracket = FormatStyle::BAS_Align;
style.AlignConsecutiveAssignments = false;
style.AlignConsecutiveDeclarations = false;
style.AlignEscapedNewlines = FormatStyle::ENAS_DontAlign;
style.AlignOperands = true;
style.AlignTrailingComments = true;
style.AllowAllParametersOfDeclarationOnNextLine = true;
style.AllowShortBlocksOnASingleLine = false;
style.AllowShortCaseLabelsOnASingleLine = false;
style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
style.AllowShortIfStatementsOnASingleLine = false;
style.AllowShortLoopsOnASingleLine = false;
style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
style.AlwaysBreakBeforeMultilineStrings = false;
style.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
style.BinPackArguments = false;
style.BinPackParameters = false;
style.BraceWrapping.AfterClass = true;
style.BraceWrapping.AfterControlStatement = false;
style.BraceWrapping.AfterEnum = false;
style.BraceWrapping.AfterFunction = true;
style.BraceWrapping.AfterNamespace = false;
style.BraceWrapping.AfterObjCDeclaration = false;
style.BraceWrapping.AfterStruct = true;
style.BraceWrapping.AfterUnion = false;
style.BraceWrapping.BeforeCatch = false;
style.BraceWrapping.BeforeElse = false;
style.BraceWrapping.IndentBraces = false;
style.BraceWrapping.SplitEmptyFunction = false;
style.BraceWrapping.SplitEmptyRecord = false;
style.BraceWrapping.SplitEmptyNamespace = false;
style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
style.BreakBeforeBraces = FormatStyle::BS_Custom;
style.BreakBeforeTernaryOperators = true;
style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
style.BreakAfterJavaFieldAnnotations = false;
style.BreakStringLiterals = true;
style.ColumnLimit = 100;
style.CommentPragmas = "^ IWYU pragma:";
style.CompactNamespaces = false;
style.ConstructorInitializerAllOnOneLineOrOnePerLine = false;
style.ConstructorInitializerIndentWidth = 4;
style.ContinuationIndentWidth = 4;
style.Cpp11BracedListStyle = true;
style.DerivePointerAlignment = false;
style.DisableFormat = false;
style.ExperimentalAutoDetectBinPacking = false;
style.FixNamespaceComments = true;
style.ForEachMacros = {"forever", "foreach", "Q_FOREACH", "BOOST_FOREACH"};
style.IncludeStyle.IncludeCategories = {{"^<Q.*", 200}};
style.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
style.IndentCaseLabels = false;
style.IndentWidth = 4;
style.IndentWrappedFunctionNames = false;
style.JavaScriptQuotes = FormatStyle::JSQS_Leave;
style.JavaScriptWrapImports = true;
style.KeepEmptyLinesAtTheStartOfBlocks = false;
// Do not add QT_BEGIN_NAMESPACE/QT_END_NAMESPACE as this will indent lines in between.
style.MacroBlockBegin = "";
style.MacroBlockEnd = "";
style.MaxEmptyLinesToKeep = 1;
style.NamespaceIndentation = FormatStyle::NI_None;
style.ObjCBlockIndentWidth = 4;
style.ObjCSpaceAfterProperty = false;
style.ObjCSpaceBeforeProtocolList = true;
style.PenaltyBreakAssignment = 150;
style.PenaltyBreakBeforeFirstCallParameter = 300;
style.PenaltyBreakComment = 500;
style.PenaltyBreakFirstLessLess = 400;
style.PenaltyBreakString = 600;
style.PenaltyExcessCharacter = 50;
style.PenaltyReturnTypeOnItsOwnLine = 300;
style.PointerAlignment = FormatStyle::PAS_Right;
style.ReflowComments = false;
style.SortIncludes = true;
style.SortUsingDeclarations = true;
style.SpaceAfterCStyleCast = true;
style.SpaceAfterTemplateKeyword = false;
style.SpaceBeforeAssignmentOperators = true;
style.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
style.SpaceInEmptyParentheses = false;
style.SpacesBeforeTrailingComments = 1;
style.SpacesInAngles = false;
style.SpacesInContainerLiterals = false;
style.SpacesInCStyleCastParentheses = false;
style.SpacesInParentheses = false;
style.SpacesInSquareBrackets = false;
style.Standard = FormatStyle::LS_Cpp11;
style.TabWidth = 4;
style.UseTab = FormatStyle::UT_Never;
return style;
}
static void applyTabSettings(clang::format::FormatStyle &style, const TabSettings &settings) static void applyTabSettings(clang::format::FormatStyle &style, const TabSettings &settings)
{ {
style.IndentWidth = static_cast<unsigned>(settings.m_indentSize); style.IndentWidth = static_cast<unsigned>(settings.m_indentSize);
@@ -63,42 +164,26 @@ static void applyTabSettings(clang::format::FormatStyle &style, const TabSetting
} }
} }
static void applyCppCodeStyleSettings(clang::format::FormatStyle &style, static bool useGlobalOverriddenSettings()
const CppCodeStyleSettings &settings)
{ {
style.IndentCaseLabels = settings.indentSwitchLabels; return ClangFormatSettings::instance().overrideDefaultFile();
style.AlignOperands = settings.alignAssignments;
style.NamespaceIndentation = FormatStyle::NI_None;
if (settings.indentNamespaceBody)
style.NamespaceIndentation = FormatStyle::NI_All;
style.BraceWrapping.IndentBraces = false;
if (settings.indentBlockBraces) {
if (settings.indentClassBraces && settings.indentEnumBraces
&& settings.indentNamespaceBraces && settings.indentFunctionBraces) {
style.BraceWrapping.IndentBraces = true;
} else {
style.BreakBeforeBraces = FormatStyle::BS_GNU;
}
}
if (settings.bindStarToIdentifier || settings.bindStarToRightSpecifier)
style.PointerAlignment = FormatStyle::PAS_Right;
else
style.PointerAlignment = FormatStyle::PAS_Left;
style.AccessModifierOffset = settings.indentAccessSpecifiers
? 0
: - static_cast<int>(style.IndentWidth);
} }
static Utils::FileName projectPath() QString currentProjectUniqueId()
{ {
const Project *project = SessionManager::startupProject(); const Project *project = SessionManager::startupProject();
if (project) if (!project)
return project->projectDirectory(); return QString();
return Utils::FileName(); return QString::fromUtf8(QCryptographicHash::hash(project->projectFilePath().toString().toUtf8(),
QCryptographicHash::Md5)
.toHex(0));
}
static bool useProjectOverriddenSettings()
{
const Project *project = SessionManager::startupProject();
return project ? project->namedSettings(Constants::OVERRIDE_FILE_ID).toBool() : false;
} }
static Utils::FileName globalPath() static Utils::FileName globalPath()
@@ -106,29 +191,59 @@ static Utils::FileName globalPath()
return Utils::FileName::fromString(Core::ICore::userResourcePath()); return Utils::FileName::fromString(Core::ICore::userResourcePath());
} }
static QString configForFile(Utils::FileName fileName) static Utils::FileName projectPath()
{ {
Utils::FileName topProjectPath = projectPath(); const Project *project = SessionManager::startupProject();
if (topProjectPath.isEmpty()) if (project)
return QString(); return globalPath().appendPath("clang-format").appendPath(currentProjectUniqueId());
QDir projectDir(fileName.parentDir().toString()); return Utils::FileName();
while (!projectDir.exists(Constants::SETTINGS_FILE_NAME)
&& !projectDir.exists(Constants::SETTINGS_FILE_ALT_NAME)) {
if (projectDir.path() == topProjectPath.toString()
|| !Utils::FileName::fromString(projectDir.path()).isChildOf(topProjectPath)
|| !projectDir.cdUp()) {
return QString();
}
}
if (projectDir.exists(Constants::SETTINGS_FILE_NAME))
return projectDir.filePath(Constants::SETTINGS_FILE_NAME);
return projectDir.filePath(Constants::SETTINGS_FILE_ALT_NAME);
} }
static clang::format::FormatStyle constructStyle(bool isGlobal, static QString findConfig(Utils::FileName fileName)
const QByteArray &baseStyle = QByteArray()) {
QDir parentDir(fileName.parentDir().toString());
while (!parentDir.exists(Constants::SETTINGS_FILE_NAME)
&& !parentDir.exists(Constants::SETTINGS_FILE_ALT_NAME)) {
if (!parentDir.cdUp())
return QString();
}
if (parentDir.exists(Constants::SETTINGS_FILE_NAME))
return parentDir.filePath(Constants::SETTINGS_FILE_NAME);
return parentDir.filePath(Constants::SETTINGS_FILE_ALT_NAME);
}
static QString configForFile(Utils::FileName fileName, bool checkForSettings)
{
QDir overrideDir;
if (!checkForSettings || useProjectOverriddenSettings()) {
overrideDir = projectPath().toString();
if (!overrideDir.isEmpty() && overrideDir.exists(Constants::SETTINGS_FILE_NAME))
return overrideDir.filePath(Constants::SETTINGS_FILE_NAME);
}
if (!checkForSettings || useGlobalOverriddenSettings()) {
overrideDir = globalPath().toString();
if (!overrideDir.isEmpty() && overrideDir.exists(Constants::SETTINGS_FILE_NAME))
return overrideDir.filePath(Constants::SETTINGS_FILE_NAME);
}
return findConfig(fileName);
}
QString configForFile(Utils::FileName fileName)
{
return configForFile(fileName, true);
}
Utils::FileName assumedPathForConfig(const QString &configFile)
{
Utils::FileName fileName = Utils::FileName::fromString(configFile);
return fileName.parentDir().appendPath("test.cpp");
}
static clang::format::FormatStyle constructStyle(const QByteArray &baseStyle = QByteArray())
{ {
if (!baseStyle.isEmpty()) { if (!baseStyle.isEmpty()) {
// Try to get the style for this base style. // Try to get the style for this base style.
@@ -144,21 +259,7 @@ static clang::format::FormatStyle constructStyle(bool isGlobal,
// Fallthrough to the default style. // Fallthrough to the default style.
} }
FormatStyle style = getLLVMStyle(); return qtcStyle();
style.BreakBeforeBraces = FormatStyle::BS_Custom;
const CppCodeStyleSettings codeStyleSettings = isGlobal
? CppCodeStyleSettings::currentGlobalCodeStyle()
: CppCodeStyleSettings::currentProjectCodeStyle()
.value_or(CppCodeStyleSettings::currentGlobalCodeStyle());
const TabSettings tabSettings = isGlobal
? CppCodeStyleSettings::currentGlobalTabSettings()
: CppCodeStyleSettings::currentProjectTabSettings();
applyTabSettings(style, tabSettings);
applyCppCodeStyleSettings(style, codeStyleSettings);
return style;
} }
void createStyleFileIfNeeded(bool isGlobal) void createStyleFileIfNeeded(bool isGlobal)
@@ -169,9 +270,21 @@ void createStyleFileIfNeeded(bool isGlobal)
if (QFile::exists(configFile)) if (QFile::exists(configFile))
return; return;
QDir().mkpath(path.parentDir().toString());
if (!isGlobal) {
const Project *project = SessionManager::startupProject();
Utils::FileName possibleProjectConfig = project->rootProjectDirectory().appendPath(
Constants::SETTINGS_FILE_NAME);
if (possibleProjectConfig.exists()) {
// Just copy th .clang-format if current project has one.
QFile::copy(possibleProjectConfig.toString(), configFile);
return;
}
}
std::fstream newStyleFile(configFile.toStdString(), std::fstream::out); std::fstream newStyleFile(configFile.toStdString(), std::fstream::out);
if (newStyleFile.is_open()) { if (newStyleFile.is_open()) {
newStyleFile << clang::format::configurationAsText(constructStyle(isGlobal)); newStyleFile << clang::format::configurationAsText(constructStyle());
newStyleFile.close(); newStyleFile.close();
} }
} }
@@ -198,17 +311,13 @@ static QByteArray configBaseStyleName(const QString &configFile)
.trimmed(); .trimmed();
} }
clang::format::FormatStyle styleForFile(Utils::FileName fileName) static clang::format::FormatStyle styleForFile(Utils::FileName fileName, bool checkForSettings)
{ {
bool isGlobal = false; QString configFile = configForFile(fileName, checkForSettings);
QString configFile = configForFile(fileName); if (configFile.isEmpty())
if (configFile.isEmpty()) { return constructStyle();
Utils::FileName path = fileName = globalPath();
fileName.appendPath(Constants::SAMPLE_FILE_NAME);
createStyleFileIfNeeded(true);
configFile = path.appendPath(Constants::SETTINGS_FILE_NAME).toString();
}
fileName = assumedPathForConfig(configFile);
Expected<FormatStyle> style = format::getStyle("file", Expected<FormatStyle> style = format::getStyle("file",
fileName.toString().toStdString(), fileName.toString().toStdString(),
"none"); "none");
@@ -219,17 +328,21 @@ clang::format::FormatStyle styleForFile(Utils::FileName fileName)
// do nothing // do nothing
}); });
return constructStyle(isGlobal, configBaseStyleName(configFile)); return constructStyle(configBaseStyleName(configFile));
}
clang::format::FormatStyle styleForFile(Utils::FileName fileName)
{
return styleForFile(fileName, true);
} }
clang::format::FormatStyle currentProjectStyle() clang::format::FormatStyle currentProjectStyle()
{ {
return styleForFile(projectPath().appendPath(Constants::SAMPLE_FILE_NAME)); return styleForFile(projectPath().appendPath(Constants::SAMPLE_FILE_NAME), false);
} }
clang::format::FormatStyle currentGlobalStyle() clang::format::FormatStyle currentGlobalStyle()
{ {
return styleForFile(globalPath().appendPath(Constants::SAMPLE_FILE_NAME)); return styleForFile(globalPath().appendPath(Constants::SAMPLE_FILE_NAME), false);
}
} }
} // namespace ClangFormat

View File

@@ -25,6 +25,7 @@
#pragma once #pragma once
#include <coreplugin/id.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <clang/Format/Format.h> #include <clang/Format/Format.h>
@@ -37,10 +38,13 @@ namespace ClangFormat {
// Creates the style for the current project or the global style if needed. // Creates the style for the current project or the global style if needed.
void createStyleFileIfNeeded(bool isGlobal); void createStyleFileIfNeeded(bool isGlobal);
QString currentProjectUniqueId();
clang::format::FormatStyle currentProjectStyle(); clang::format::FormatStyle currentProjectStyle();
clang::format::FormatStyle currentGlobalStyle(); clang::format::FormatStyle currentGlobalStyle();
// Is the style from the matching .clang-format file or global one if it's not found. // Is the style from the matching .clang-format file or global one if it's not found.
QString configForFile(Utils::FileName fileName);
clang::format::FormatStyle styleForFile(Utils::FileName fileName); clang::format::FormatStyle styleForFile(Utils::FileName fileName);
} }

View File

@@ -452,12 +452,12 @@ void ClangTidyClazyTool::handleStateUpdate()
if (issuesFound) if (issuesFound)
message = tr("Running - %n diagnostics", nullptr, issuesFound); message = tr("Running - %n diagnostics", nullptr, issuesFound);
else else
message = tr("Running - No diagnostics", nullptr, issuesFound); message = tr("Running - No diagnostics");
} else { } else {
if (issuesFound) if (issuesFound)
message = tr("Finished - %n diagnostics", nullptr, issuesFound); message = tr("Finished - %n diagnostics", nullptr, issuesFound);
else else
message = tr("Finished - No diagnostics", nullptr, issuesFound); message = tr("Finished - No diagnostics");
} }
Debugger::showPermanentStatusMessage(message); Debugger::showPermanentStatusMessage(message);

View File

@@ -78,6 +78,21 @@ void SearchResultTreeView::addResults(const QList<SearchResultItem> &items, Sear
} }
} }
void SearchResultTreeView::keyPressEvent(QKeyEvent *event)
{
if ((event->key() == Qt::Key_Return
|| event->key() == Qt::Key_Enter)
&& event->modifiers() == 0
&& currentIndex().isValid()
&& state() != QAbstractItemView::EditingState) {
const SearchResultItem item
= model()->data(currentIndex(), ItemDataRoles::ResultItemRole).value<SearchResultItem>();
emit jumpToSearchResult(item);
return;
}
TreeView::keyPressEvent(event);
}
void SearchResultTreeView::emitJumpToSearchResult(const QModelIndex &index) void SearchResultTreeView::emitJumpToSearchResult(const QModelIndex &index)
{ {
if (model()->data(index, ItemDataRoles::IsGeneratedRole).toBool()) if (model()->data(index, ItemDataRoles::IsGeneratedRole).toBool())

View File

@@ -49,6 +49,8 @@ public:
SearchResultTreeModel *model() const; SearchResultTreeModel *model() const;
void addResults(const QList<SearchResultItem> &items, SearchResult::AddMode mode); void addResults(const QList<SearchResultItem> &items, SearchResult::AddMode mode);
void keyPressEvent(QKeyEvent *event) override;
signals: signals:
void jumpToSearchResult(const SearchResultItem &item); void jumpToSearchResult(const SearchResultItem &item);

View File

@@ -84,10 +84,9 @@ public:
const Links &links() const; const Links &links() const;
const Links bestLinks() const; const Links bestLinks() const;
const QString keyword() const; const QString keyword() const;
private:
bool isFuzzyMatch() const; bool isFuzzyMatch() const;
private:
QUrl m_helpUrl; QUrl m_helpUrl;
QStringList m_helpIds; QStringList m_helpIds;
QString m_docMark; QString m_docMark;

View File

@@ -252,6 +252,14 @@ void LocatorModel::addEntries(const QList<LocatorFilterEntry> &entries)
CompletionList::CompletionList(QWidget *parent) CompletionList::CompletionList(QWidget *parent)
: Utils::TreeView(parent) : Utils::TreeView(parent)
{ {
// on macOS and Windows the popup doesn't really get focus, so fake the selection color
// which would then just be a very light gray, but should look as if it had focus
QPalette p = palette();
p.setBrush(QPalette::Inactive,
QPalette::Highlight,
p.brush(QPalette::Normal, QPalette::Highlight));
setPalette(p);
setItemDelegate(new CompletionDelegate(this)); setItemDelegate(new CompletionDelegate(this));
setRootIsDecorated(false); setRootIsDecorated(false);
setUniformRowHeights(true); setUniformRowHeights(true);

View File

@@ -507,7 +507,6 @@ void OutputPaneManager::showPage(int idx, int flags)
ensurePageVisible(idx); ensurePageVisible(idx);
IOutputPane *out = g_outputPanes.at(idx).pane; IOutputPane *out = g_outputPanes.at(idx).pane;
out->visibilityChanged(true);
if (flags & IOutputPane::WithFocus) { if (flags & IOutputPane::WithFocus) {
if (out->canFocus()) if (out->canFocus())
out->setFocus(); out->setFocus();
@@ -538,7 +537,10 @@ void OutputPaneManager::setCurrentIndex(int idx)
m_outputWidgetPane->setCurrentIndex(idx); m_outputWidgetPane->setCurrentIndex(idx);
m_opToolBarWidgets->setCurrentIndex(idx); m_opToolBarWidgets->setCurrentIndex(idx);
IOutputPane *pane = g_outputPanes.at(idx).pane; OutputPaneData &data = g_outputPanes[idx];
IOutputPane *pane = data.pane;
data.button->show();
data.buttonVisible = true;
pane->visibilityChanged(true); pane->visibilityChanged(true);
bool canNavigate = pane->canNavigate(); bool canNavigate = pane->canNavigate();
@@ -574,8 +576,6 @@ void OutputPaneManager::popupMenu()
data.button->hide(); data.button->hide();
data.buttonVisible = false; data.buttonVisible = false;
} else { } else {
data.button->show();
data.buttonVisible = true;
showPage(idx, IOutputPane::ModeSwitch); showPage(idx, IOutputPane::ModeSwitch);
} }
} }

View File

@@ -860,11 +860,11 @@ void ClangDiagnosticConfigsWidget::syncClazyChecksGroupBox()
return !m_clazySortFilterProxyModel->filterAcceptsRow(index.row(), index.parent()); return !m_clazySortFilterProxyModel->filterAcceptsRow(index.row(), index.parent());
}; };
const bool hasEnabledButHidden = m_clazyTreeModel->hasEnabledButNotVisibleChecks(isHidden); const bool hasEnabledButHidden = m_clazyTreeModel->hasEnabledButNotVisibleChecks(isHidden);
const QString title = hasEnabledButHidden ? tr("Checks (%1 enabled, some are filtered out)") const int checksCount = m_clazyTreeModel->enabledChecks().count();
: tr("Checks (%1 enabled)"); const QString title = hasEnabledButHidden ? tr("Checks (%n enabled, some are filtered out)",
nullptr, checksCount)
const QStringList checks = m_clazyTreeModel->enabledChecks(); : tr("Checks (%n enabled)", nullptr, checksCount);
m_clazyChecks->checksGroupBox->setTitle(title.arg(checks.count())); m_clazyChecks->checksGroupBox->setTitle(title);
} }
void ClangDiagnosticConfigsWidget::updateConfig(const ClangDiagnosticConfig &config) void ClangDiagnosticConfigsWidget::updateConfig(const ClangDiagnosticConfig &config)

View File

@@ -172,7 +172,7 @@ void CompilerOptionsBuilder::addSyntaxOnly()
isClStyle() ? add("/Zs") : add("-fsyntax-only"); isClStyle() ? add("/Zs") : add("-fsyntax-only");
} }
static QStringList createLanguageOptionGcc(ProjectFile::Kind fileKind, bool objcExt) QStringList createLanguageOptionGcc(ProjectFile::Kind fileKind, bool objcExt)
{ {
QStringList options; QStringList options;
@@ -741,6 +741,15 @@ void CompilerOptionsBuilder::evaluateCompilerFlags()
continue; continue;
} }
if (option.startsWith("/Y", Qt::CaseSensitive)
|| (option.startsWith("/F", Qt::CaseSensitive) && option != "/F")) {
// Precompiled header flags.
// Skip also the next option if it's not glued to the current one.
if (option.size() > 3)
skipNext = true;
continue;
}
// Check whether a language version is already used. // Check whether a language version is already used.
QString theOption = option; QString theOption = option;
if (theOption.startsWith("-std=")) { if (theOption.startsWith("-std=")) {

View File

@@ -40,6 +40,7 @@ enum class UseBuildSystemWarnings : char { Yes, No };
CPPTOOLS_EXPORT QStringList XclangArgs(const QStringList &args); CPPTOOLS_EXPORT QStringList XclangArgs(const QStringList &args);
CPPTOOLS_EXPORT QStringList clangArgsForCl(const QStringList &args); CPPTOOLS_EXPORT QStringList clangArgsForCl(const QStringList &args);
CPPTOOLS_EXPORT QStringList createLanguageOptionGcc(ProjectFile::Kind fileKind, bool objcExt);
class CPPTOOLS_EXPORT CompilerOptionsBuilder class CPPTOOLS_EXPORT CompilerOptionsBuilder
{ {

View File

@@ -99,10 +99,10 @@ These prefixes are used in addition to current file name on Switch Header/Source
<item row="7" column="1"> <item row="7" column="1">
<widget class="QCheckBox" name="headerPragmaOnceCheckBox"> <widget class="QCheckBox" name="headerPragmaOnceCheckBox">
<property name="toolTip"> <property name="toolTip">
<string>Uses #pragma once instead of #ifndef include guards.</string> <string>Uses &quot;#pragma once&quot; instead of &quot;#ifndef&quot; include guards.</string>
</property> </property>
<property name="text"> <property name="text">
<string>Use '#pragma once' instead of '#ifndef' guards</string> <string>Use &quot;#pragma once&quot; instead of &quot;#ifndef&quot; guards</string>
</property> </property>
</widget> </widget>
</item> </item>

View File

@@ -211,7 +211,7 @@ bool CppToolsPlugin::initialize(const QStringList &arguments, QString *error)
expander->registerVariable( expander->registerVariable(
"Cpp:PragmaOnce", "Cpp:PragmaOnce",
tr("Insert #pragma once instead of #ifndef include guards into header file"), tr("Insert \"#pragma once\" instead of \"#ifndef\" include guards into header file"),
[] { return usePragmaOnce() ? QString("true") : QString(); }); [] { return usePragmaOnce() ? QString("true") : QString(); });
return true; return true;

View File

@@ -58,7 +58,7 @@ public:
QWidget *outputWidget(QWidget *) override; QWidget *outputWidget(QWidget *) override;
QList<QWidget *> toolBarWidgets() const override; QList<QWidget *> toolBarWidgets() const override;
QString displayName() const override { return tr("Debugger Console"); } QString displayName() const override { return tr("QML Debugger Console"); }
int priorityInStatusBar() const override; int priorityInStatusBar() const override;
void clearContents() override; void clearContents() override;
void visibilityChanged(bool visible) override; void visibilityChanged(bool visible) override;

View File

@@ -748,7 +748,8 @@ void DebuggerItemManagerPrivate::autoDetectGdbOrLldbDebuggers()
dir.setPath(base.toFileInfo().absoluteFilePath()); dir.setPath(base.toFileInfo().absoluteFilePath());
foreach (const QString &entry, dir.entryList()) { foreach (const QString &entry, dir.entryList()) {
if (entry.startsWith("lldb-platform-") if (entry.startsWith("lldb-platform-")
|| entry.startsWith("lldb-gdbserver-")) { || entry.startsWith("lldb-gdbserver-")
|| entry.startsWith("lldb-mi-")) {
continue; continue;
} }
suspects.append(FileName::fromString(dir.absoluteFilePath(entry))); suspects.append(FileName::fromString(dir.absoluteFilePath(entry)));

View File

@@ -152,24 +152,7 @@ DebuggerKitAspect::DebuggerKitAspect()
setPriority(28000); setPriority(28000);
} }
QVariant DebuggerKitAspect::defaultValue(const Kit *k) const QVariant DebuggerKitAspect::defaultValue(const Kit *) const { return QVariant(); }
{
const Abi toolChainAbi = ToolChainKitAspect::targetAbi(k);
const Utils::FileNameList paths = Environment::systemEnvironment().path();
QVariant nextBestFit;
for (const DebuggerItem &item : DebuggerItemManager::debuggers()) {
for (const Abi &targetAbi : item.abis()) {
if (targetAbi.isCompatibleWith(toolChainAbi)) {
if (paths.contains(item.command()))
return item.id(); // prefer debuggers found in PATH over those found elsewhere
if (nextBestFit.isNull())
nextBestFit = item.id();
}
}
}
return nextBestFit;
}
void DebuggerKitAspect::setup(Kit *k) void DebuggerKitAspect::setup(Kit *k)
{ {

View File

@@ -119,6 +119,7 @@ public:
void resetCurrentPerspective(); void resetCurrentPerspective();
int indexInChooser(Perspective *perspective) const; int indexInChooser(Perspective *perspective) const;
void fixupLayoutIfNeeded(); void fixupLayoutIfNeeded();
void updatePerspectiveChooserWidth();
DebuggerMainWindow *q = nullptr; DebuggerMainWindow *q = nullptr;
Perspective *m_currentPerspective = nullptr; Perspective *m_currentPerspective = nullptr;
@@ -416,10 +417,17 @@ void DebuggerMainWindowPrivate::selectPerspective(Perspective *perspective)
fixupLayoutIfNeeded(); fixupLayoutIfNeeded();
} }
updatePerspectiveChooserWidth();
}
void DebuggerMainWindowPrivate::updatePerspectiveChooserWidth()
{
Perspective *perspective = m_currentPerspective;
int index = indexInChooser(m_currentPerspective); int index = indexInChooser(m_currentPerspective);
if (index == -1) { if (index == -1) {
if (Perspective *parent = Perspective::findPerspective(m_currentPerspective->d->m_parentPerspectiveId)) perspective = Perspective::findPerspective(m_currentPerspective->d->m_parentPerspectiveId);
index = indexInChooser(parent); if (perspective)
index = indexInChooser(perspective);
} }
if (index != -1) { if (index != -1) {

View File

@@ -61,6 +61,7 @@
#include <utils/temporarydirectory.h> #include <utils/temporarydirectory.h>
#include <utils/temporaryfile.h> #include <utils/temporaryfile.h>
#include <utils/url.h> #include <utils/url.h>
#include <utils/winutils.h>
#include <coreplugin/icontext.h> #include <coreplugin/icontext.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
@@ -565,6 +566,17 @@ void DebuggerRunTool::start()
if (!fixupParameters()) if (!fixupParameters())
return; return;
if (m_runParameters.cppEngineType == CdbEngineType
&& Utils::is64BitWindowsBinary(m_runParameters.inferior.executable)
&& !Utils::is64BitWindowsBinary(m_runParameters.debugger.executable)) {
reportFailure(
DebuggerPlugin::tr(
"%1 is a 64 bit executable which can not be debugged by a 32 bit Debugger.\n"
"Please select a 64 bit Debugger in the kit settings for this kit.")
.arg(m_runParameters.inferior.executable));
return;
}
Utils::globalMacroExpander()->registerFileVariables( Utils::globalMacroExpander()->registerFileVariables(
"DebuggedExecutable", tr("Debugged executable"), "DebuggedExecutable", tr("Debugged executable"),
[this] { return m_runParameters.inferior.executable; } [this] { return m_runParameters.inferior.executable; }

View File

@@ -395,6 +395,8 @@ void LldbEngine::handleResponse(const QString &response)
handleOutputNotification(item); handleOutputNotification(item);
else if (name == "pid") else if (name == "pid")
notifyInferiorPid(item.toProcessHandle()); notifyInferiorPid(item.toProcessHandle());
else if (name == "breakpointmodified")
handleInterpreterBreakpointModified(item);
} }
} }
@@ -607,6 +609,31 @@ void LldbEngine::handleOutputNotification(const GdbMi &output)
showMessage(data, ch); showMessage(data, ch);
} }
void LldbEngine::handleInterpreterBreakpointModified(const GdbMi &bpItem)
{
QTC_ASSERT(bpItem.childCount(), return);
QString id = bpItem.childAt(0).m_data;
Breakpoint bp = breakHandler()->findBreakpointByResponseId(id);
if (!bp) // FIXME adapt whole bp handling and turn into soft assert
return;
// this function got triggered by a lldb internal breakpoint event
// avoid asserts regarding unexpected state transitions
switch (bp->state()) {
case BreakpointInsertionRequested: // was a pending bp
bp->gotoState(BreakpointInsertionProceeding, BreakpointInsertionRequested);
break;
case BreakpointInserted: // was an inserted, gets updated now
bp->gotoState(BreakpointUpdateRequested, BreakpointInserted);
notifyBreakpointChangeProceeding(bp);
break;
default:
break;
}
updateBreakpointData(bp, bpItem, false);
}
void LldbEngine::loadSymbols(const QString &moduleName) void LldbEngine::loadSymbols(const QString &moduleName)
{ {
Q_UNUSED(moduleName) Q_UNUSED(moduleName)

View File

@@ -120,6 +120,7 @@ private:
void handleStateNotification(const GdbMi &item); void handleStateNotification(const GdbMi &item);
void handleLocationNotification(const GdbMi &location); void handleLocationNotification(const GdbMi &location);
void handleOutputNotification(const GdbMi &output); void handleOutputNotification(const GdbMi &output);
void handleInterpreterBreakpointModified(const GdbMi &item);
void handleResponse(const QString &data); void handleResponse(const QString &data);
void updateAll() override; void updateAll() override;

View File

@@ -657,7 +657,7 @@ void HelpPluginPrivate::showContextHelp(const HelpItem &contextHelp)
.arg(contextHelp.helpIds().join(", ")) .arg(contextHelp.helpIds().join(", "))
.arg(HelpPlugin::tr("No documentation available."))); .arg(HelpPlugin::tr("No documentation available.")));
} }
} else if (links.size() == 1) { } else if (links.size() == 1 && !contextHelp.isFuzzyMatch()) {
showHelpUrl(links.front().second, LocalHelpManager::contextHelpOption()); showHelpUrl(links.front().second, LocalHelpManager::contextHelpOption());
} else { } else {
QMap<QString, QUrl> map; QMap<QString, QUrl> map;

View File

@@ -208,17 +208,6 @@ void Client::openDocument(Core::IDocument *document)
connect(textDocument, &QObject::destroyed, this, [this, textDocument]{ connect(textDocument, &QObject::destroyed, this, [this, textDocument]{
m_resetAssistProvider.remove(textDocument); m_resetAssistProvider.remove(textDocument);
}); });
if (BaseTextEditor *editor = BaseTextEditor::textEditorForDocument(textDocument)) {
if (QPointer<TextEditorWidget> widget = editor->editorWidget()) {
connect(widget, &TextEditorWidget::cursorPositionChanged, this, [this, widget](){
// TODO This would better be a compressing timer
QTimer::singleShot(50, this, [this, widget]() {
if (widget)
cursorPositionChanged(widget);
});
});
}
}
} }
m_openedDocument.append(document->filePath()); m_openedDocument.append(document->filePath());
@@ -344,7 +333,7 @@ void Client::documentContentsChanged(Core::IDocument *document)
if (textDocument) { if (textDocument) {
using namespace TextEditor; using namespace TextEditor;
if (BaseTextEditor *editor = BaseTextEditor::textEditorForDocument(textDocument)) for (BaseTextEditor *editor : BaseTextEditor::textEditorsForDocument(textDocument))
if (TextEditorWidget *widget = editor->editorWidget()) if (TextEditorWidget *widget = editor->editorWidget())
widget->setRefactorMarkers(RefactorMarker::filterOutType(widget->refactorMarkers(), id())); widget->setRefactorMarkers(RefactorMarker::filterOutType(widget->refactorMarkers(), id()));
requestDocumentSymbols(textDocument); requestDocumentSymbols(textDocument);
@@ -766,6 +755,11 @@ const DynamicCapabilities &Client::dynamicCapabilities() const
return m_dynamicCapabilities; return m_dynamicCapabilities;
} }
const BaseClientInterface *Client::clientInterface() const
{
return m_clientInterface.data();
}
void Client::log(const ShowMessageParams &message, void Client::log(const ShowMessageParams &message,
Core::MessageManager::PrintToOutputPaneFlag flag) Core::MessageManager::PrintToOutputPaneFlag flag)
{ {

View File

@@ -147,6 +147,7 @@ public:
const LanguageServerProtocol::ServerCapabilities &capabilities() const; const LanguageServerProtocol::ServerCapabilities &capabilities() const;
const DynamicCapabilities &dynamicCapabilities() const; const DynamicCapabilities &dynamicCapabilities() const;
const BaseClientInterface *clientInterface() const;
signals: signals:
void initialized(LanguageServerProtocol::ServerCapabilities capabilities); void initialized(LanguageServerProtocol::ServerCapabilities capabilities);

View File

@@ -110,7 +110,7 @@ StdIOClientInterface::~StdIOClientInterface()
Utils::SynchronousProcess::stopProcess(m_process); Utils::SynchronousProcess::stopProcess(m_process);
} }
bool StdIOClientInterface::needsRestart(const StdIOSettings *settings) bool StdIOClientInterface::needsRestart(const StdIOSettings *settings) const
{ {
return m_executable != settings->m_executable || m_arguments != settings->m_arguments; return m_executable != settings->m_executable || m_arguments != settings->m_arguments;
} }

View File

@@ -74,7 +74,7 @@ public:
StdIOClientInterface &operator=(const StdIOClientInterface &) = delete; StdIOClientInterface &operator=(const StdIOClientInterface &) = delete;
StdIOClientInterface &operator=(StdIOClientInterface &&) = delete; StdIOClientInterface &operator=(StdIOClientInterface &&) = delete;
bool needsRestart(const StdIOSettings *settings); bool needsRestart(const StdIOSettings *settings) const;
bool start() override; bool start() override;

View File

@@ -125,7 +125,10 @@ void LanguageClientManager::deleteClient(Client *client)
QTC_ASSERT(client, return); QTC_ASSERT(client, return);
client->disconnect(); client->disconnect();
managerInstance->m_clients.removeAll(client); managerInstance->m_clients.removeAll(client);
client->deleteLater(); if (managerInstance->m_shuttingDown)
delete client;
else
client->deleteLater();
} }
void LanguageClientManager::shutdown() void LanguageClientManager::shutdown()
@@ -210,6 +213,18 @@ void LanguageClientManager::editorOpened(Core::IEditor *editor)
(const QTextCursor &cursor){ (const QTextCursor &cursor){
findUsages(filePath, cursor); findUsages(filePath, cursor);
}); });
connect(widget, &TextEditorWidget::cursorPositionChanged, this, [this, widget](){
// TODO This would better be a compressing timer
QTimer::singleShot(50, this,
[this, widget = QPointer<TextEditorWidget>(widget)]() {
if (widget) {
for (Client *client : this->reachableClients()) {
if (client->isSupportedDocument(widget->textDocument()))
client->cursorPositionChanged(widget);
}
}
});
});
} }
} }
} }

View File

@@ -491,7 +491,9 @@ bool StdIOSettings::needsRestart() const
{ {
if (BaseSettings::needsRestart()) if (BaseSettings::needsRestart())
return true; return true;
if (auto stdIOInterface = qobject_cast<StdIOClientInterface *>(m_client)) if (m_client.isNull())
return false;
if (auto stdIOInterface = qobject_cast<const StdIOClientInterface *>(m_client->clientInterface()))
return stdIOInterface->needsRestart(this); return stdIOInterface->needsRestart(this);
return false; return false;
} }

View File

@@ -133,12 +133,10 @@ void updateCodeActionRefactoringMarker(Client *client,
TextDocument* doc = TextDocument::textDocumentForFileName(uri.toFileName()); TextDocument* doc = TextDocument::textDocumentForFileName(uri.toFileName());
if (!doc) if (!doc)
return; return;
BaseTextEditor *editor = BaseTextEditor::textEditorForDocument(doc); const QVector<BaseTextEditor *> editors = BaseTextEditor::textEditorsForDocument(doc);
if (!editor) if (editors.isEmpty())
return; return;
TextEditorWidget *editorWidget = editor->editorWidget();
const QList<Diagnostic> &diagnostics = action.diagnostics().value_or(QList<Diagnostic>()); const QList<Diagnostic> &diagnostics = action.diagnostics().value_or(QList<Diagnostic>());
RefactorMarkers markers; RefactorMarkers markers;
@@ -181,7 +179,10 @@ void updateCodeActionRefactoringMarker(Client *client,
marker.cursor = endOfLineCursor(diagnostic.range().start().toTextCursor(doc->document())); marker.cursor = endOfLineCursor(diagnostic.range().start().toTextCursor(doc->document()));
markers << marker; markers << marker;
} }
editorWidget->setRefactorMarkers(markers + editorWidget->refactorMarkers()); for (BaseTextEditor *editor : editors) {
if (TextEditorWidget *editorWidget = editor->editorWidget())
editorWidget->setRefactorMarkers(markers + editorWidget->refactorMarkers());
}
} }
} // namespace LanguageClient } // namespace LanguageClient

View File

@@ -10,9 +10,6 @@
<height>300</height> <height>300</height>
</rect> </rect>
</property> </property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="groupBox">

View File

@@ -96,7 +96,7 @@ PerfTracePointDialog::~PerfTracePointDialog()
void PerfTracePointDialog::runScript() void PerfTracePointDialog::runScript()
{ {
m_ui->label->setText(tr("Executing script ...")); m_ui->label->setText(tr("Executing script..."));
m_ui->textEdit->setReadOnly(true); m_ui->textEdit->setReadOnly(true);
m_ui->privilegesChooser->setEnabled(false); m_ui->privilegesChooser->setEnabled(false);
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);

View File

@@ -41,6 +41,8 @@ namespace Ui { class PerfTracePointDialog; }
class PerfTracePointDialog : public QDialog class PerfTracePointDialog : public QDialog
{ {
Q_OBJECT
public: public:
PerfTracePointDialog(); PerfTracePointDialog();
~PerfTracePointDialog(); ~PerfTracePointDialog();

View File

@@ -59,7 +59,6 @@ SUBDIRS = \
languageclient \ languageclient \
cppcheck \ cppcheck \
compilationdatabaseprojectmanager \ compilationdatabaseprojectmanager \
perfprofiler \
qmlpreview \ qmlpreview \
studiowelcome studiowelcome
@@ -70,9 +69,9 @@ qtHaveModule(serialport) {
} }
qtHaveModule(quick) { qtHaveModule(quick) {
SUBDIRS += qmlprofiler SUBDIRS += qmlprofiler perfprofiler
} else { } else {
warning("QmlProfiler plugin has been disabled since the Qt Quick module is not available.") warning("QmlProfiler and PerfProfiler plugins have been disabled since the Qt Quick module is not available.")
} }
qtHaveModule(help) { qtHaveModule(help) {

View File

@@ -32,6 +32,8 @@ namespace Internal {
class DesktopDeviceFactory : public IDeviceFactory class DesktopDeviceFactory : public IDeviceFactory
{ {
Q_OBJECT
public: public:
DesktopDeviceFactory(); DesktopDeviceFactory();
}; };

View File

@@ -275,11 +275,9 @@ void Kit::fix()
void Kit::setup() void Kit::setup()
{ {
KitGuard g(this); KitGuard g(this);
// Process the KitAspects in reverse order: They may only be based on other information
// lower in the stack.
const QList<KitAspect *> aspects = KitManager::kitAspects(); const QList<KitAspect *> aspects = KitManager::kitAspects();
for (int i = aspects.count() - 1; i >= 0; --i) for (KitAspect * const aspect : aspects)
aspects.at(i)->setup(this); aspect->setup(this);
} }
void Kit::upgrade() void Kit::upgrade()

View File

@@ -71,10 +71,12 @@ class KitManagerPrivate
public: public:
Kit *m_defaultKit = nullptr; Kit *m_defaultKit = nullptr;
bool m_initialized = false; bool m_initialized = false;
std::vector<std::unique_ptr<KitAspect>> m_informationList;
std::vector<std::unique_ptr<Kit>> m_kitList; std::vector<std::unique_ptr<Kit>> m_kitList;
std::unique_ptr<PersistentSettingsWriter> m_writer; std::unique_ptr<PersistentSettingsWriter> m_writer;
QSet<Id> m_irrelevantAspects; QSet<Id> m_irrelevantAspects;
// Sorted by priority, in descending order.
std::vector<std::unique_ptr<KitAspect>> m_informationList;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -1027,6 +1027,8 @@ bool static hasFlagEffectOnMacros(const QString &flag)
return false; // Skip include paths return false; // Skip include paths
if (f.startsWith("w", Qt::CaseInsensitive)) if (f.startsWith("w", Qt::CaseInsensitive))
return false; // Skip warning options return false; // Skip warning options
if (f.startsWith("Y") || (f.startsWith("F") && f != "F"))
return false; // Skip pch-related flags
} }
return true; return true;
} }

View File

@@ -2045,8 +2045,12 @@ void ProjectExplorerPluginPrivate::updateWelcomePage()
void ProjectExplorerPluginPrivate::currentModeChanged(Id mode, Id oldMode) void ProjectExplorerPluginPrivate::currentModeChanged(Id mode, Id oldMode)
{ {
if (oldMode == Constants::MODE_SESSION) if (oldMode == Constants::MODE_SESSION) {
ICore::saveSettings(); // Saving settings directly in a mode change is not a good idea, since the mode change
// can be part of a bigger change. Save settings after that bigger change had a chance to
// complete.
QTimer::singleShot(0, ICore::instance(), &ICore::saveSettings);
}
if (mode == Core::Constants::MODE_WELCOME) if (mode == Core::Constants::MODE_WELCOME)
updateWelcomePage(); updateWelcomePage();
} }

View File

@@ -363,7 +363,7 @@ static QStringList readLinesJson(const Utils::FileName &projectFile,
// This assumes te project file is formed with only one field called // This assumes te project file is formed with only one field called
// 'files' that has a list associated of the files to include in the project. // 'files' that has a list associated of the files to include in the project.
if (content.isEmpty()) { if (content.isEmpty()) {
*errorMessage = PythonProject::tr("Unable read \"%1\": The file is empty.") *errorMessage = PythonProject::tr("Unable to read \"%1\": The file is empty.")
.arg(projectFile.toUserOutput()); .arg(projectFile.toUserOutput());
return lines; return lines;
} }
@@ -372,7 +372,7 @@ static QStringList readLinesJson(const Utils::FileName &projectFile,
const QJsonDocument doc = QJsonDocument::fromJson(content, &error); const QJsonDocument doc = QJsonDocument::fromJson(content, &error);
if (doc.isNull()) { if (doc.isNull()) {
const int line = content.left(error.offset).count('\n') + 1; const int line = content.left(error.offset).count('\n') + 1;
*errorMessage = PythonProject::tr("Unable parse %1:%2: %3") *errorMessage = PythonProject::tr("Unable to parse \"%1\":%2: %3")
.arg(projectFile.toUserOutput()).arg(line) .arg(projectFile.toUserOutput()).arg(line)
.arg(error.errorString()); .arg(error.errorString());
return lines; return lines;

View File

@@ -71,10 +71,10 @@ public:
void toogleRecording(bool b) const; void toogleRecording(bool b) const;
void resetGroupRecording() const; void resetGroupRecording() const;
bool hasKeyframeGroup(const ModelNode &node, const PropertyName &propertyName) const;
private: private:
void addKeyframeGroupIfNotExists(const ModelNode &node, const PropertyName &propertyName); void addKeyframeGroupIfNotExists(const ModelNode &node, const PropertyName &propertyName);
bool hasKeyframeGroup(const ModelNode &node, const PropertyName &propertyName) const;
QList<QmlTimelineKeyframeGroup> allKeyframeGroups() const; QList<QmlTimelineKeyframeGroup> allKeyframeGroups() const;
}; };

View File

@@ -63,7 +63,7 @@ void QmlObjectNode::setVariantProperty(const PropertyName &name, const QVariant
timelineFrames.setValue(value, frame); timelineFrames.setValue(value, frame);
return; return;
} else if (modelNode().hasId() && timelineIsActive()) { } else if (modelNode().hasId() && timelineIsActive() && currentTimeline().hasKeyframeGroup(modelNode(), name)) {
QmlTimelineKeyframeGroup timelineFrames(currentTimeline().keyframeGroup(modelNode(), name)); QmlTimelineKeyframeGroup timelineFrames(currentTimeline().keyframeGroup(modelNode(), name));
Q_ASSERT(timelineFrames.isValid()); Q_ASSERT(timelineFrames.isValid());

View File

@@ -65,7 +65,6 @@ const char REFORMAT_UI_QML_FILES[] = "ReformatUiQmlFiles"; /* These setti
const char IGNORE_DEVICE_PIXEL_RATIO[] = "IgnoreDevicePixelRaio"; /* The settings can be used to turn off the feature, if there are serious issues */ const char IGNORE_DEVICE_PIXEL_RATIO[] = "IgnoreDevicePixelRaio"; /* The settings can be used to turn off the feature, if there are serious issues */
const char STANDALONE_MODE[] = "StandAloneMode"; const char STANDALONE_MODE[] = "StandAloneMode";
const char ENABLE_TIMELINEVIEW[] = "EnableTimelineView"; const char ENABLE_TIMELINEVIEW[] = "EnableTimelineView";
const char ENABLE_TIMELINEVIEW_ENVVAR[] = "QTC_ENABLE_QTQUICKTIMELINE_EDITOR";
} }
class DesignerSettings : public QHash<QByteArray, QVariant> class DesignerSettings : public QHash<QByteArray, QVariant>

View File

@@ -10,14 +10,11 @@
<height>176</height> <height>176</height>
</rect> </rect>
</property> </property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="4" column="3"> <item row="4" column="3">
<widget class="QLabel" name="label_16"> <widget class="QLabel" name="label_16">
<property name="text"> <property name="text">
<string>Loops</string> <string>Loops:</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -117,7 +114,7 @@
</size> </size>
</property> </property>
<property name="text"> <property name="text">
<string>Animation ID</string> <string>Animation ID:</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -162,14 +159,14 @@
<item row="5" column="1"> <item row="5" column="1">
<widget class="QLabel" name="label_23"> <widget class="QLabel" name="label_23">
<property name="text"> <property name="text">
<string>Finished</string> <string>Finished:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="7"> <item row="4" column="7">
<widget class="QLabel" name="label_17"> <widget class="QLabel" name="label_17">
<property name="text"> <property name="text">
<string>Ping Pong</string> <string>Ping pong</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -205,7 +202,7 @@
</size> </size>
</property> </property>
<property name="text"> <property name="text">
<string>Transition to state</string> <string>Transition to state:</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -222,7 +219,7 @@
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="text"> <property name="text">
<string>Running in Base State</string> <string>Running in base state</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -257,7 +254,7 @@
<item row="3" column="1"> <item row="3" column="1">
<widget class="QLabel" name="label_12"> <widget class="QLabel" name="label_12">
<property name="text"> <property name="text">
<string>Start Frame</string> <string>Start frame:</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -290,14 +287,14 @@
<item row="3" column="7"> <item row="3" column="7">
<widget class="QLabel" name="label_14"> <widget class="QLabel" name="label_14">
<property name="text"> <property name="text">
<string>Duration</string> <string>Duration:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="3"> <item row="3" column="3">
<widget class="QLabel" name="label_13"> <widget class="QLabel" name="label_13">
<property name="text"> <property name="text">
<string>End Frame</string> <string>End frame:</string>
</property> </property>
</widget> </widget>
</item> </item>

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2018 The Qt Company Ltd. ** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of Qt Creator. ** This file is part of Qt Creator.
@@ -46,13 +46,13 @@ const int priorityTimelineCategory = 110;
const char timelineCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Timeline"); const char timelineCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Timeline");
const char timelineCopyKeyframesDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", const char timelineCopyKeyframesDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu",
"Copy All Keyframes from item"); "Copy All Keyframes");
const char timelinePasteKeyframesDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", const char timelinePasteKeyframesDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu",
"Paste Keyframes to item"); "Paste Keyframes");
const char timelineInsertKeyframesDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", const char timelineInsertKeyframesDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu",
"Insert Keyframes for item"); "Add Keyframes at Current Frame");
const char timelineDeleteKeyframesDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", const char timelineDeleteKeyframesDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu",
"Delete All Keyframes for item"); "Delete All Keyframes");
const char timelineStatusBarFrameNumber[] = QT_TRANSLATE_NOOP("QmlDesignerTimeline", "Frame %1"); const char timelineStatusBarFrameNumber[] = QT_TRANSLATE_NOOP("QmlDesignerTimeline", "Frame %1");

View File

@@ -10,9 +10,6 @@
<height>170</height> <height>170</height>
</rect> </rect>
</property> </property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="1" column="8" colspan="2"> <item row="1" column="8" colspan="2">
<spacer name="horizontalSpacer_11"> <spacer name="horizontalSpacer_11">
@@ -84,7 +81,7 @@
<item row="4" column="0"> <item row="4" column="0">
<widget class="QLabel" name="label_8"> <widget class="QLabel" name="label_8">
<property name="text"> <property name="text">
<string>Expression Binding</string> <string>Expression binding:</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
@@ -107,7 +104,7 @@
<item row="2" column="4"> <item row="2" column="4">
<widget class="QLabel" name="label_7"> <widget class="QLabel" name="label_7">
<property name="text"> <property name="text">
<string>End Frame</string> <string>End frame:</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
@@ -200,7 +197,7 @@
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="text"> <property name="text">
<string>Expression Binding</string> <string>Expression binding</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -214,7 +211,7 @@
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="label_5"> <widget class="QLabel" name="label_5">
<property name="text"> <property name="text">
<string>Timeline ID</string> <string>Timeline ID:</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
@@ -243,7 +240,7 @@
<item row="2" column="1"> <item row="2" column="1">
<widget class="QLabel" name="label_6"> <widget class="QLabel" name="label_6">
<property name="text"> <property name="text">
<string>Start Frame</string> <string>Start frame:</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>

View File

@@ -44,6 +44,8 @@ class TimelineToolButton;
class TimelineKeyframeItem : public TimelineMovableAbstractItem class TimelineKeyframeItem : public TimelineMovableAbstractItem
{ {
Q_DECLARE_TR_FUNCTIONS(TimelineKeyframeItem)
public: public:
explicit TimelineKeyframeItem(TimelinePropertyItem *parent, const ModelNode &frame); explicit TimelineKeyframeItem(TimelinePropertyItem *parent, const ModelNode &frame);
~TimelineKeyframeItem() override; ~TimelineKeyframeItem() override;
@@ -84,6 +86,8 @@ private:
class TimelinePropertyItem : public TimelineItem class TimelinePropertyItem : public TimelineItem
{ {
Q_OBJECT
public: public:
enum { Type = TimelineConstants::timelinePropertyItemUserType }; enum { Type = TimelineConstants::timelinePropertyItemUserType };

View File

@@ -40,6 +40,8 @@ class TimelineSectionItem;
class TimelineBarItem : public TimelineMovableAbstractItem class TimelineBarItem : public TimelineMovableAbstractItem
{ {
Q_DECLARE_TR_FUNCTIONS(TimelineBarItem)
enum class Location { Undefined, Center, Left, Right }; enum class Location { Undefined, Center, Left, Right };
public: public:

View File

@@ -103,7 +103,7 @@ QWidget *TimelineEditorDelegate::createEditor(QWidget *parent,
switch (index.column()) { switch (index.column()) {
case TimelineSettingsModel::TimelineRow: { case TimelineSettingsModel::TimelineRow: {
QTC_ASSERT(comboBox, return widget); QTC_ASSERT(comboBox, return widget);
comboBox->addItem(tr("None")); comboBox->addItem(TimelineSettingsModel::tr("None"));
for (const auto &timeline : timelineSettingsModel->timelineView()->getTimelines()) { for (const auto &timeline : timelineSettingsModel->timelineView()->getTimelines()) {
if (!timeline.modelNode().id().isEmpty()) if (!timeline.modelNode().id().isEmpty())
comboBox->addItem(timeline.modelNode().id()); comboBox->addItem(timeline.modelNode().id());
@@ -111,7 +111,7 @@ QWidget *TimelineEditorDelegate::createEditor(QWidget *parent,
} break; } break;
case TimelineSettingsModel::AnimationRow: { case TimelineSettingsModel::AnimationRow: {
QTC_ASSERT(comboBox, return widget); QTC_ASSERT(comboBox, return widget);
comboBox->addItem(tr("None")); comboBox->addItem(TimelineSettingsModel::tr("None"));
for (const auto &animation : for (const auto &animation :
timelineSettingsModel->timelineView()->getAnimations(qmlTimeline)) { timelineSettingsModel->timelineView()->getAnimations(qmlTimeline)) {
if (!animation.id().isEmpty()) if (!animation.id().isEmpty())

View File

@@ -194,8 +194,7 @@ bool QmlDesignerPlugin::delayedInitialize()
d->settings.fromSettings(Core::ICore::settings()); d->settings.fromSettings(Core::ICore::settings());
d->viewManager.registerViewTakingOwnership(new QmlDesigner::Internal::ConnectionView); d->viewManager.registerViewTakingOwnership(new QmlDesigner::Internal::ConnectionView);
if (DesignerSettings::getValue(DesignerSettingsKey::ENABLE_TIMELINEVIEW).toBool() if (DesignerSettings::getValue(DesignerSettingsKey::ENABLE_TIMELINEVIEW).toBool())
|| qEnvironmentVariableIsSet(DesignerSettingsKey::ENABLE_TIMELINEVIEW_ENVVAR))
d->viewManager.registerViewTakingOwnership(new QmlDesigner::TimelineView); d->viewManager.registerViewTakingOwnership(new QmlDesigner::TimelineView);
d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::SourceTool); d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::SourceTool);
d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::ColorTool); d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::ColorTool);

View File

@@ -159,6 +159,8 @@ DesignerSettings SettingsPageWidget::settings() const
m_ui.showPropertyEditorWarningsCheckBox->isChecked()); m_ui.showPropertyEditorWarningsCheckBox->isChecked());
settings.insert(DesignerSettingsKey::ENABLE_MODEL_EXCEPTION_OUTPUT, settings.insert(DesignerSettingsKey::ENABLE_MODEL_EXCEPTION_OUTPUT,
m_ui.showWarnExceptionsCheckBox->isChecked()); m_ui.showWarnExceptionsCheckBox->isChecked());
settings.insert(DesignerSettingsKey::ENABLE_TIMELINEVIEW,
m_ui.featureTimelineEditorCheckBox->isChecked());
return settings; return settings;
} }
@@ -224,9 +226,13 @@ void SettingsPageWidget::setSettings(const DesignerSettings &settings)
m_ui.controls2StyleComboBox->setCurrentText(m_ui.styleLineEdit->text()); m_ui.controls2StyleComboBox->setCurrentText(m_ui.styleLineEdit->text());
m_ui.featureTimelineEditorCheckBox->setChecked(settings.value(
DesignerSettingsKey::ENABLE_TIMELINEVIEW).toBool());
if (settings.value(DesignerSettingsKey::STANDALONE_MODE).toBool()) { if (settings.value(DesignerSettingsKey::STANDALONE_MODE).toBool()) {
m_ui.emulationGroupBox->hide(); m_ui.emulationGroupBox->hide();
m_ui.debugGroupBox->hide(); m_ui.debugGroupBox->hide();
m_ui.featuresGroupBox->hide();
} }
} }
@@ -262,7 +268,8 @@ void SettingsPage::apply()
<< DesignerSettingsKey::PUPPET_KILL_TIMEOUT << DesignerSettingsKey::PUPPET_KILL_TIMEOUT
<< DesignerSettingsKey::FORWARD_PUPPET_OUTPUT << DesignerSettingsKey::FORWARD_PUPPET_OUTPUT
<< DesignerSettingsKey::DEBUG_PUPPET << DesignerSettingsKey::DEBUG_PUPPET
<< DesignerSettingsKey::ENABLE_MODEL_EXCEPTION_OUTPUT; << DesignerSettingsKey::ENABLE_MODEL_EXCEPTION_OUTPUT
<< DesignerSettingsKey::ENABLE_TIMELINEVIEW;
foreach (const QByteArray &key, restartNecessaryKeys) { foreach (const QByteArray &key, restartNecessaryKeys) {
if (currentSettings.value(key) != newSettings.value(key)) { if (currentSettings.value(key) != newSettings.value(key)) {

View File

@@ -410,6 +410,22 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QGroupBox" name="featuresGroupBox">
<property name="title">
<string>Features</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QCheckBox" name="featureTimelineEditorCheckBox">
<property name="text">
<string>Enable Timeline editor</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QGroupBox" name="debugGroupBox"> <widget class="QGroupBox" name="debugGroupBox">
<property name="title"> <property name="title">

View File

@@ -287,10 +287,10 @@ void QmlProfilerTool::updateRunActions()
d->m_startAction->setToolTip(tr("A QML Profiler analysis is still in progress.")); d->m_startAction->setToolTip(tr("A QML Profiler analysis is still in progress."));
d->m_stopAction->setEnabled(true); d->m_stopAction->setEnabled(true);
} else { } else {
QString whyNot = tr("Start QML Profiler analysis."); QString tooltip = tr("Start QML Profiler analysis.");
bool canRun = ProjectExplorerPlugin::canRunStartupProject bool canRun = ProjectExplorerPlugin::canRunStartupProject
(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE, &whyNot); (ProjectExplorer::Constants::QML_PROFILER_RUN_MODE, &tooltip);
d->m_startAction->setToolTip(whyNot); d->m_startAction->setToolTip(tooltip);
d->m_startAction->setEnabled(canRun); d->m_startAction->setEnabled(canRun);
d->m_stopAction->setEnabled(false); d->m_stopAction->setEnabled(false);
} }

View File

@@ -31,6 +31,7 @@
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/ansiescapecodehandler.h> #include <utils/ansiescapecodehandler.h>
#include <utils/fileinprojectfinder.h> #include <utils/fileinprojectfinder.h>
#include <utils/hostosinfo.h>
#include <utils/theme/theme.h> #include <utils/theme/theme.h>
#include <QPlainTextEdit> #include <QPlainTextEdit>
@@ -412,16 +413,16 @@ void QtSupportPlugin::testQtOutputFormatter_data()
<< " Loc: [../TestProject/test.cpp(123)]" << " Loc: [../TestProject/test.cpp(123)]"
<< 9 << 37 << "../TestProject/test.cpp(123)" << 9 << 37 << "../TestProject/test.cpp(123)"
<< "../TestProject/test.cpp" << 123 << -1; << "../TestProject/test.cpp" << 123 << -1;
if (HostOsInfo::isWindowsHost()) {
QTest::newRow("Windows failed QTest link") QTest::newRow("Windows failed QTest link")
<< "..\\TestProject\\test.cpp(123) : failure location" << "..\\TestProject\\test.cpp(123) : failure location"
<< 0 << 28 << "..\\TestProject\\test.cpp(123)" << 0 << 28 << "..\\TestProject\\test.cpp(123)"
<< "..\\TestProject\\test.cpp" << 123 << -1; << "../TestProject/test.cpp" << 123 << -1;
QTest::newRow("Windows failed QTest link with carriage return")
QTest::newRow("Windows failed QTest link with carriage return") << "..\\TestProject\\test.cpp(123) : failure location\r"
<< "..\\TestProject\\test.cpp(123) : failure location\r" << 0 << 28 << "..\\TestProject\\test.cpp(123)"
<< 0 << 28 << "..\\TestProject\\test.cpp(123)" << "../TestProject/test.cpp" << 123 << -1;
<< "..\\TestProject\\test.cpp" << 123 << -1; }
} }
void QtSupportPlugin::testQtOutputFormatter() void QtSupportPlugin::testQtOutputFormatter()

View File

@@ -203,7 +203,7 @@ void AbstractRemoteLinuxDeployService::handleDeviceSetupDone(bool success)
} else { } else {
connect(d->connection, &SshConnection::connected, connect(d->connection, &SshConnection::connected,
this, &AbstractRemoteLinuxDeployService::handleConnected); this, &AbstractRemoteLinuxDeployService::handleConnected);
emit progressMessage(tr("Connecting to device '%1' (%2)") emit progressMessage(tr("Connecting to device \"%1\" (%2).")
.arg(deviceConfiguration()->displayName()) .arg(deviceConfiguration()->displayName())
.arg(deviceConfiguration()->sshParameters().host())); .arg(deviceConfiguration()->sshParameters().host()));
if (d->connection->state() == SshConnection::Unconnected) if (d->connection->state() == SshConnection::Unconnected)

View File

@@ -145,7 +145,7 @@ void BaseHoverHandler::decorateToolTip()
if (Qt::mightBeRichText(toolTip())) if (Qt::mightBeRichText(toolTip()))
setToolTip(toolTip().toHtmlEscaped()); setToolTip(toolTip().toHtmlEscaped());
if (lastHelpItemIdentified().isValid()) { if (lastHelpItemIdentified().isValid() && !lastHelpItemIdentified().isFuzzyMatch()) {
const QString &helpContents = lastHelpItemIdentified().extractContent(false); const QString &helpContents = lastHelpItemIdentified().extractContent(false);
if (!helpContents.isEmpty()) { if (!helpContents.isEmpty()) {
m_toolTip = toolTip().toHtmlEscaped(); m_toolTip = toolTip().toHtmlEscaped();

View File

@@ -258,6 +258,16 @@ void Highlighter::handleShutdown()
delete highlightRepository(); delete highlightRepository();
} }
static bool isOpeningParenthesis(QChar c)
{
return c == QLatin1Char('{') || c == QLatin1Char('[') || c == QLatin1Char('(');
}
static bool isClosingParenthesis(QChar c)
{
return c == QLatin1Char('}') || c == QLatin1Char(']') || c == QLatin1Char(')');
}
void Highlighter::highlightBlock(const QString &text) void Highlighter::highlightBlock(const QString &text)
{ {
if (!definition().isValid()) if (!definition().isValid())
@@ -266,8 +276,21 @@ void Highlighter::highlightBlock(const QString &text)
KSyntaxHighlighting::State state = TextDocumentLayout::userData(block)->syntaxState(); KSyntaxHighlighting::State state = TextDocumentLayout::userData(block)->syntaxState();
state = highlightLine(text, state); state = highlightLine(text, state);
block = block.next(); block = block.next();
Parentheses parentheses;
int pos = 0;
for (const QChar &c : text) {
if (isOpeningParenthesis(c))
parentheses.push_back(Parenthesis(Parenthesis::Opened, c, pos));
else if (isClosingParenthesis(c))
parentheses.push_back(Parenthesis(Parenthesis::Closed, c, pos));
pos++;
}
TextDocumentLayout::setParentheses(currentBlock(), parentheses);
if (block.isValid()) if (block.isValid())
TextDocumentLayout::userData(block)->setSyntaxState(state); TextDocumentLayout::userData(block)->setSyntaxState(state);
formatSpaces(text);
} }
void Highlighter::applyFormat(int offset, int length, const KSyntaxHighlighting::Format &format) void Highlighter::applyFormat(int offset, int length, const KSyntaxHighlighting::Format &format)

View File

@@ -127,6 +127,9 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="resetCache"> <widget class="QPushButton" name="resetCache">
<property name="toolTip">
<string>Reset definitions remembered for files that can be associated with more than one highlighter definition.</string>
</property>
<property name="text"> <property name="text">
<string>Reset Remembered Definitions</string> <string>Reset Remembered Definitions</string>
</property> </property>

View File

@@ -8508,13 +8508,14 @@ BaseTextEditor *BaseTextEditor::currentTextEditor()
return qobject_cast<BaseTextEditor *>(EditorManager::currentEditor()); return qobject_cast<BaseTextEditor *>(EditorManager::currentEditor());
} }
BaseTextEditor *BaseTextEditor::textEditorForDocument(TextDocument *textDocument) QVector<BaseTextEditor *> BaseTextEditor::textEditorsForDocument(TextDocument *textDocument)
{ {
QVector<BaseTextEditor *> ret;
for (IEditor *editor : Core::DocumentModel::editorsForDocument(textDocument)) { for (IEditor *editor : Core::DocumentModel::editorsForDocument(textDocument)) {
if (auto textEditor = qobject_cast<BaseTextEditor *>(editor)) if (auto textEditor = qobject_cast<BaseTextEditor *>(editor))
return textEditor; ret << textEditor;
} }
return nullptr; return ret;
} }
TextEditorWidget *BaseTextEditor::editorWidget() const TextEditorWidget *BaseTextEditor::editorWidget() const

View File

@@ -111,7 +111,7 @@ public:
virtual void finalizeInitialization() {} virtual void finalizeInitialization() {}
static BaseTextEditor *currentTextEditor(); static BaseTextEditor *currentTextEditor();
static BaseTextEditor *textEditorForDocument(TextDocument *textDocument); static QVector<BaseTextEditor *> textEditorsForDocument(TextDocument *textDocument);
TextEditorWidget *editorWidget() const; TextEditorWidget *editorWidget() const;
TextDocument *textDocument() const; TextDocument *textDocument() const;

View File

@@ -2,7 +2,19 @@ DEFINES += TEXTEDITOR_LIBRARY
QT += gui-private network printsupport xml QT += gui-private network printsupport xml
CONFIG += exceptions CONFIG += exceptions
CONFIG += include_source_dir # For the highlighter autotest. CONFIG += include_source_dir # For the highlighter autotest.
include(../../shared/syntax/syntax_shared.pri)
isEmpty(KSYNTAXHIGHLIGHTING_LIB_DIR) | isEmpty(KSYNTAXHIGHLIGHTING_INCLUDE_DIR) {
QTC_LIB_DEPENDS += syntax-highlighting
} else {
unix:!disable_external_rpath {
!macos: QMAKE_LFLAGS += -Wl,-z,origin
QMAKE_LFLAGS += -Wl,-rpath,$$shell_quote($${KSYNTAXHIGHLIGHTING_LIB_DIR})
}
}
include(../../qtcreatorplugin.pri) include(../../qtcreatorplugin.pri)
SOURCES += texteditorplugin.cpp \ SOURCES += texteditorplugin.cpp \
plaintexteditorfactory.cpp \ plaintexteditorfactory.cpp \
textdocument.cpp \ textdocument.cpp \

View File

@@ -2,7 +2,21 @@ QTC_PLUGIN_NAME = TextEditor
QTC_LIB_DEPENDS += \ QTC_LIB_DEPENDS += \
aggregation \ aggregation \
extensionsystem \ extensionsystem \
utils \ utils
syntax-highlighting
QTC_PLUGIN_DEPENDS += \ QTC_PLUGIN_DEPENDS += \
coreplugin coreplugin
# needed for plugins that depend on TextEditor plugin
include(../../shared/syntax/syntax_shared.pri)
!isEmpty(KSYNTAXHIGHLIGHTING_LIB_DIR):!isEmpty(KSYNTAXHIGHLIGHTING_INCLUDE_DIR) {
INCLUDEPATH *= $${KSYNTAXHIGHLIGHTING_INCLUDE_DIR}
LIBS *= -L$$KSYNTAXHIGHLIGHTING_LIB_DIR -lKF5SyntaxHighlighting
linux {
QMAKE_LFLAGS += -Wl,-z,origin
QMAKE_LFLAGS += -Wl,-rpath,$$shell_quote($${KSYNTAXHIGHLIGHTING_LIB_DIR})
}
} else {
QTC_LIB_DEPENDS += syntax-highlighting
}

View File

@@ -96,7 +96,16 @@ defineReplace(splitFlags) {
flag ~= s,-I\S*,, flag ~= s,-I\S*,,
flag ~= s,/D\S*,, flag ~= s,/D\S*,,
flag ~= s,/Z\S*,, flag ~= s,/Z\S*,,
result += $$split(flag, " ") separate_flags = $$split(flag, " ")
for (separate_flag, separate_flags) {
starting_substr = $$str_member($$separate_flag, 0, 0)
win32:equals(starting_substr, "/") {
result += $$separate_flag
}
equals(starting_substr, "-") {
result += $$separate_flag
}
}
} else { } else {
inside_quotes = 0 inside_quotes = 0
starting_substr = $$str_member($$flag, 0, 0) starting_substr = $$str_member($$flag, 0, 0)

View File

@@ -0,0 +1,21 @@
# KSyntaxHighlighting uses a special folder structure (may contain target arch triple for the lib),
# so expect lib folder to be specified by the user - generate include path based on this
isEmpty(KSYNTAXHIGHLIGHTING_LIB_DIR): KSYNTAXHIGHLIGHTING_LIB_DIR=$$(KSYNTAXHIGHLIGHTING_LIB_DIR)
isEmpty(KSYNTAXHIGHLIGHTING_INCLUDE_DIR): KSYNTAXHIGHLIGHTING_INCLUDE_DIR=$$(KSYNTAXHIGHLIGHTING_INCLUDE_DIR)
!isEmpty(KSYNTAXHIGHLIGHTING_LIB_DIR) {
!exists($$KSYNTAXHIGHLIGHTING_LIB_DIR) {
unset(KSYNTAXHIGHLIGHTING_LIB_DIR)
unset(KSYNTAXHIGHLIGHTING_INCLUDE_DIR)
} else {
isEmpty(KSYNTAXHIGHLIGHTING_INCLUDE_DIR) {
!linux: KSYNTAXHIGHLIGHTING_INCLUDE_DIR=$$absolute_path('../include/KF5/KSyntaxHighlighting/', $$KSYNTAXHIGHLIGHTING_LIB_DIR)
else: KSYNTAXHIGHLIGHTING_INCLUDE_DIR=$$absolute_path('../../include/KF5/KSyntaxHighlighting/', $$KSYNTAXHIGHLIGHTING_LIB_DIR)
}
!exists($$KSYNTAXHIGHLIGHTING_INCLUDE_DIR) {
unset(KSYNTAXHIGHLIGHTING_INCLUDE_DIR)
unset(KSYNTAXHIGHLIGHTING_LIB_DIR)
}
}
}

View File

@@ -181,6 +181,7 @@ void FullTokenInfo::variableKind(const Cursor &cursor)
{ {
TokenInfo::variableKind(cursor); TokenInfo::variableKind(cursor);
m_extraInfo.accessSpecifier = cursor.accessSpecifier();
m_extraInfo.storageClass = cursor.storageClass(); m_extraInfo.storageClass = cursor.storageClass();
} }

View File

@@ -41,7 +41,7 @@
#include <precompiledheaderstorage.h> #include <precompiledheaderstorage.h>
#include <processormanager.h> #include <processormanager.h>
#include <progresscounter.h> #include <progresscounter.h>
#include <projectparts.h> #include <projectpartsmanager.h>
#include <filepathcaching.h> #include <filepathcaching.h>
#include <refactoringdatabaseinitializer.h> #include <refactoringdatabaseinitializer.h>
#include <sqlitedatabase.h> #include <sqlitedatabase.h>
@@ -68,7 +68,7 @@ using ClangBackEnd::PchCreator;
using ClangBackEnd::PchManagerClientProxy; using ClangBackEnd::PchManagerClientProxy;
using ClangBackEnd::PchManagerServer; using ClangBackEnd::PchManagerServer;
using ClangBackEnd::PrecompiledHeaderStorage; using ClangBackEnd::PrecompiledHeaderStorage;
using ClangBackEnd::ProjectParts; using ClangBackEnd::ProjectPartsManager;
using ClangBackEnd::FilePathCache; using ClangBackEnd::FilePathCache;
using ClangBackEnd::FilePathView; using ClangBackEnd::FilePathView;
using ClangBackEnd::TimeStamp; using ClangBackEnd::TimeStamp;
@@ -138,12 +138,14 @@ public:
ClangBackEnd::Environment &environment, ClangBackEnd::Environment &environment,
Sqlite::Database &database, Sqlite::Database &database,
PchManagerServer &pchManagerServer, PchManagerServer &pchManagerServer,
ClangBackEnd::ClangPathWatcherInterface &pathWatcher) ClangBackEnd::ClangPathWatcherInterface &pathWatcher,
: ProcessorManager(generatedFiles), ClangBackEnd::BuildDependenciesStorageInterface &buildDependenciesStorage)
m_environment(environment), : ProcessorManager(generatedFiles)
m_database(database), , m_environment(environment)
m_pchManagerServer(pchManagerServer), , m_database(database)
m_pathWatcher(pathWatcher) , m_pchManagerServer(pchManagerServer)
, m_pathWatcher(pathWatcher)
, m_buildDependenciesStorage(buildDependenciesStorage)
{} {}
protected: protected:
@@ -152,7 +154,8 @@ protected:
return std::make_unique<PchCreator>(m_environment, return std::make_unique<PchCreator>(m_environment,
m_database, m_database,
*m_pchManagerServer.client(), *m_pchManagerServer.client(),
m_pathWatcher); m_pathWatcher,
m_buildDependenciesStorage);
} }
private: private:
@@ -160,6 +163,7 @@ private:
Sqlite::Database &m_database; Sqlite::Database &m_database;
ClangBackEnd::PchManagerServer &m_pchManagerServer; ClangBackEnd::PchManagerServer &m_pchManagerServer;
ClangBackEnd::ClangPathWatcherInterface &m_pathWatcher; ClangBackEnd::ClangPathWatcherInterface &m_pathWatcher;
ClangBackEnd::BuildDependenciesStorageInterface &m_buildDependenciesStorage;
}; };
struct Data // because we have a cycle dependency struct Data // because we have a cycle dependency
@@ -175,13 +179,14 @@ struct Data // because we have a cycle dependency
ClangBackEnd::FilePathCaching filePathCache{database}; ClangBackEnd::FilePathCaching filePathCache{database};
ClangPathWatcher<QFileSystemWatcher, QTimer> includeWatcher{filePathCache}; ClangPathWatcher<QFileSystemWatcher, QTimer> includeWatcher{filePathCache};
ApplicationEnvironment environment; ApplicationEnvironment environment;
ProjectParts projectParts; ProjectPartsManager projectParts;
GeneratedFiles generatedFiles; GeneratedFiles generatedFiles;
PchCreatorManager pchCreatorManager{generatedFiles, PchCreatorManager pchCreatorManager{generatedFiles,
environment, environment,
database, database,
clangPchManagerServer, clangPchManagerServer,
includeWatcher}; includeWatcher,
buildDependencyStorage};
PrecompiledHeaderStorage<> preCompiledHeaderStorage{database}; PrecompiledHeaderStorage<> preCompiledHeaderStorage{database};
ClangBackEnd::ProgressCounter pchCreationProgressCounter{[&](int progress, int total) { ClangBackEnd::ProgressCounter pchCreationProgressCounter{[&](int progress, int total) {
executeInLoop([&] { executeInLoop([&] {

View File

@@ -55,19 +55,19 @@ OutputContainer setUnion(InputContainer1 &&input1,
BuildDependency BuildDependenciesProvider::create(const ProjectPartContainer &projectPart) BuildDependency BuildDependenciesProvider::create(const ProjectPartContainer &projectPart)
{ {
SourceEntries includes = createSourceEntriesFromStorage(projectPart.sourcePathIds, auto sourcesAndProjectPart = createSourceEntriesFromStorage(
projectPart.projectPartId); projectPart.sourcePathIds, projectPart.projectPartId);
if (!m_modifiedTimeChecker.isUpToDate(includes)) { if (!m_modifiedTimeChecker.isUpToDate(sourcesAndProjectPart.first)) {
BuildDependency buildDependency = m_generator.create(projectPart); BuildDependency buildDependency = m_generator.create(projectPart);
storeBuildDependency(buildDependency); storeBuildDependency(buildDependency, sourcesAndProjectPart.second);
return buildDependency; return buildDependency;
} }
return createBuildDependencyFromStorage(std::move(includes)); return createBuildDependencyFromStorage(
std::move(sourcesAndProjectPart.first));
} }
BuildDependency BuildDependenciesProvider::createBuildDependencyFromStorage( BuildDependency BuildDependenciesProvider::createBuildDependencyFromStorage(
@@ -76,7 +76,7 @@ BuildDependency BuildDependenciesProvider::createBuildDependencyFromStorage(
BuildDependency buildDependency; BuildDependency buildDependency;
buildDependency.usedMacros = createUsedMacrosFromStorage(includes); buildDependency.usedMacros = createUsedMacrosFromStorage(includes);
buildDependency.includes = std::move(includes); buildDependency.sources = std::move(includes);
return buildDependency; return buildDependency;
} }
@@ -101,16 +101,19 @@ UsedMacros BuildDependenciesProvider::createUsedMacrosFromStorage(const SourceEn
return usedMacros; return usedMacros;
} }
SourceEntries BuildDependenciesProvider::createSourceEntriesFromStorage( std::pair<SourceEntries, int>
const FilePathIds &sourcePathIds, Utils::SmallStringView projectPartId) const BuildDependenciesProvider::createSourceEntriesFromStorage(
{ const FilePathIds &sourcePathIds,
Utils::SmallStringView projectPartName) const {
SourceEntries includes; SourceEntries includes;
Sqlite::DeferredTransaction transaction(m_transactionBackend); Sqlite::DeferredTransaction transaction(m_transactionBackend);
int projectPartId = m_storage.fetchProjectPartId(projectPartName);
for (FilePathId sourcePathId : sourcePathIds) { for (FilePathId sourcePathId : sourcePathIds) {
SourceEntries entries = m_storage.fetchDependSources(sourcePathId, SourceEntries entries =
projectPartId); m_storage.fetchDependSources(sourcePathId, projectPartId);
SourceEntries mergedEntries = setUnion<SourceEntries>(includes, entries); SourceEntries mergedEntries = setUnion<SourceEntries>(includes, entries);
includes = std::move(mergedEntries); includes = std::move(mergedEntries);
@@ -118,15 +121,14 @@ SourceEntries BuildDependenciesProvider::createSourceEntriesFromStorage(
transaction.commit(); transaction.commit();
return includes; return {includes, projectPartId};
} }
void BuildDependenciesProvider::storeBuildDependency(const BuildDependency &buildDependency) void BuildDependenciesProvider::storeBuildDependency(
{ const BuildDependency &buildDependency, int projectPartId) {
Sqlite::ImmediateTransaction transaction(m_transactionBackend); Sqlite::ImmediateTransaction transaction(m_transactionBackend);
m_storage.insertOrUpdateSources(buildDependency.sources, projectPartId);
m_storage.updateSources(buildDependency.includes); m_storage.insertOrUpdateFileStatuses(buildDependency.fileStatuses);
m_storage.insertFileStatuses(buildDependency.fileStatuses);
m_storage.insertOrUpdateSourceDependencies(buildDependency.sourceDependencies); m_storage.insertOrUpdateSourceDependencies(buildDependency.sourceDependencies);
m_storage.insertOrUpdateUsedMacros(buildDependency.usedMacros); m_storage.insertOrUpdateUsedMacros(buildDependency.usedMacros);

View File

@@ -55,9 +55,9 @@ public:
private: private:
BuildDependency createBuildDependencyFromStorage(SourceEntries &&includes) const; BuildDependency createBuildDependencyFromStorage(SourceEntries &&includes) const;
UsedMacros createUsedMacrosFromStorage(const SourceEntries &includes) const; UsedMacros createUsedMacrosFromStorage(const SourceEntries &includes) const;
SourceEntries createSourceEntriesFromStorage(const FilePathIds &sourcePathIds, std::pair<SourceEntries, int> createSourceEntriesFromStorage(
Utils::SmallStringView projectPartId) const; const FilePathIds &sourcePathIds, Utils::SmallStringView projectPartName) const;
void storeBuildDependency(const BuildDependency &buildDependency); void storeBuildDependency(const BuildDependency &buildDependency, int projectPartId);
private: private:
BuildDependenciesStorageInterface &m_storage; BuildDependenciesStorageInterface &m_storage;

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