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

Change-Id: I20eb743180b51dbedabced277a8f12ebe9620807
This commit is contained in:
Eike Ziller
2017-09-25 11:03:45 +02:00
311 changed files with 4011 additions and 3115 deletions

View File

@@ -57,7 +57,8 @@ For Windows:
3. Set shortcuts for convenience: 3. Set shortcuts for convenience:
In Menu: Tools > Options > Environment > Keyboard In Menu: Tools > Options > Environment > Keyboard
* ClangFormat / FormatFile - e.g. Alt+C, F * ClangFormat / FormatFile - e.g. Alt+C, F
* ClangFormat / FormatSelectedText - e.g. Alt+C, S * ClangFormat / FormatAtCursor - e.g. Alt+C, C
* ClangFormat / DisableFormattingSelectedText - e.g. Alt+C, D
Due to several issues outlined below the FormatFile action might be of limited Due to several issues outlined below the FormatFile action might be of limited
use. use.

View File

@@ -174,7 +174,13 @@
\endlist \endlist
In addition to the \uicontrol {Format Current File} command, ClangFormat In addition to the \uicontrol {Format Current File} command, ClangFormat
and Uncrustify provide the \uicontrol {Format Selected Text} command. If you and Uncrustify provide additional commands.
ClangFormat provides the \uicontrol {Format at Cursor} command. If you
select it when no text is selected, the syntactic entity under the cursor
is formatted. The \uicontrol {Disable Formatting for Selected Text} command
wraps selected lines within \c {// clang-format off} and
\c {// clang-format on}.
Uncrustify provides the \uicontrol {Format Selected Text} command. If you
select it when no text is selected, the whole file is formatted by default. select it when no text is selected, the whole file is formatted by default.
To disable this behavior, deselect the To disable this behavior, deselect the
\uicontrol {Format entire file if no text was selected} check box. \uicontrol {Format entire file if no text was selected} check box.

View File

@@ -223,8 +223,6 @@ def deploy_libclang(install_dir, llvm_install_dir, chrpath_bin):
os.path.join(install_dir, 'bin'))) os.path.join(install_dir, 'bin')))
deployinfo.append((os.path.join(llvm_install_dir, 'bin', 'clang.exe'), deployinfo.append((os.path.join(llvm_install_dir, 'bin', 'clang.exe'),
clangbindirtarget)) clangbindirtarget))
deployinfo.append((os.path.join(llvm_install_dir, 'bin', 'clang-cl.exe'),
clangbindirtarget))
resourcetarget = os.path.join(clanglibdirtarget, 'clang') resourcetarget = os.path.join(clanglibdirtarget, 'clang')
else: else:
libsources = glob(os.path.join(llvm_install_dir, 'lib', 'libclang.so*')) libsources = glob(os.path.join(llvm_install_dir, 'lib', 'libclang.so*'))

View File

@@ -1258,9 +1258,7 @@ class Dumper(DumperBase):
if not skipEventReporting: if not skipEventReporting:
self.eventState = state self.eventState = state
if state == lldb.eStateExited: if state == lldb.eStateExited:
if self.isShuttingDown_: if not self.isShuttingDown_:
self.reportState("inferiorshutdownok")
else:
self.reportState("inferiorexited") self.reportState("inferiorexited")
self.report('exited={status="%s",desc="%s"}' self.report('exited={status="%s",desc="%s"}'
% (self.process.GetExitStatus(), self.process.GetExitDescription())) % (self.process.GetExitStatus(), self.process.GetExitDescription()))
@@ -1290,7 +1288,7 @@ class Dumper(DumperBase):
return return
if self.isInterrupting_: if self.isInterrupting_:
self.isInterrupting_ = False self.isInterrupting_ = False
self.reportState("stopped") self.reportState("inferiorstopok")
elif self.ignoreStops > 0: elif self.ignoreStops > 0:
self.ignoreStops -= 1 self.ignoreStops -= 1
self.process.Continue() self.process.Continue()

View File

@@ -20,7 +20,7 @@ Module {
prototype: "QQuickItem" prototype: "QQuickItem"
Property { name: "condition"; type: "bool" } Property { name: "condition"; type: "bool" }
Property { name: "limitToSubProject"; type: "bool" } Property { name: "limitToSubProject"; type: "bool" }
Property { name: "multiplexConfigurationId"; type: "string" } Property { name: "multiplexConfigurationIds"; type: "string"; isList: true }
Property { name: "name"; type: "string" } Property { name: "name"; type: "string" }
Property { name: "productTypes"; type: "string"; isList: true } Property { name: "productTypes"; type: "string"; isList: true }
Property { name: "profiles"; type: "string"; isList: true } Property { name: "profiles"; type: "string"; isList: true }
@@ -49,6 +49,7 @@ Module {
Property { name: "condition"; type: "bool" } Property { name: "condition"; type: "bool" }
Property { name: "fileTags"; type: "string"; isList: true } Property { name: "fileTags"; type: "string"; isList: true }
Property { name: "patterns"; type: "string"; isList: true } Property { name: "patterns"; type: "string"; isList: true }
Property { name: "priority"; type: "int" }
} }
Component { Component {
name: "Group" name: "Group"
@@ -118,6 +119,14 @@ Module {
Property { name: "type"; type: "string"; isList: true } Property { name: "type"; type: "string"; isList: true }
Property { name: "version"; type: "string" } Property { name: "version"; type: "string" }
} }
Component {
name: "Profile"
exports: [ "qbs/Profile 1.0" ]
prototype: "QQuickItem"
Property { name: "baseProfile"; type: "string" }
Property { name: "condition"; type: "bool" }
Property { name: "name"; type: "string" }
}
Component { Component {
name: "Project" name: "Project"
exports: [ "qbs/Project 1.0" ] exports: [ "qbs/Project 1.0" ]

View File

@@ -157,7 +157,7 @@ void sortFilterImports(const QStringList &imports, QStringList *workingImports,
namespace QmlDesigner { namespace QmlDesigner {
static NodeInstanceServer *nodeInstanceServerInstance = 0; static NodeInstanceServer *nodeInstanceServerInstance = nullptr;
static void notifyPropertyChangeCallBackFunction(QObject *object, const PropertyName &propertyName) static void notifyPropertyChangeCallBackFunction(QObject *object, const PropertyName &propertyName)
{ {
@@ -170,11 +170,7 @@ static void (*notifyPropertyChangeCallBackPointer)(QObject *, const PropertyName
NodeInstanceServer::NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) : NodeInstanceServer::NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient) :
NodeInstanceServerInterface(), NodeInstanceServerInterface(),
m_childrenChangeEventFilter(new Internal::ChildrenChangeEventFilter(this)), m_childrenChangeEventFilter(new Internal::ChildrenChangeEventFilter(this)),
m_nodeInstanceClient(nodeInstanceClient), m_nodeInstanceClient(nodeInstanceClient)
m_timer(0),
m_renderTimerInterval(16),
m_slowRenderTimer(false),
m_slowRenderTimerInterval(200)
{ {
qmlRegisterType<DummyContextObject>("QmlDesigner", 1, 0, "DummyContextObject"); qmlRegisterType<DummyContextObject>("QmlDesigner", 1, 0, "DummyContextObject");
@@ -184,10 +180,6 @@ NodeInstanceServer::NodeInstanceServer(NodeInstanceClientInterface *nodeInstance
Internal::QmlPrivateGate::registerFixResourcePathsForObjectCallBack(); Internal::QmlPrivateGate::registerFixResourcePathsForObjectCallBack();
} }
NodeInstanceServer::~NodeInstanceServer()
{
}
QList<ServerNodeInstance> NodeInstanceServer::createInstances(const QVector<InstanceContainer> &containerVector) QList<ServerNodeInstance> NodeInstanceServer::createInstances(const QVector<InstanceContainer> &containerVector)
{ {
Q_ASSERT(declarativeView() || quickView()); Q_ASSERT(declarativeView() || quickView());
@@ -247,7 +239,7 @@ ServerNodeInstance NodeInstanceServer::instanceForObject(QObject *object) const
bool NodeInstanceServer::hasInstanceForObject(QObject *object) const bool NodeInstanceServer::hasInstanceForObject(QObject *object) const
{ {
if (object == 0) if (object == nullptr)
return false; return false;
return m_objectInstanceHash.contains(object) && m_objectInstanceHash.value(object).isValid(); return m_objectInstanceHash.contains(object) && m_objectInstanceHash.value(object).isValid();
@@ -671,7 +663,7 @@ QQmlContext *NodeInstanceServer::context() const
if (engine()) if (engine())
return rootContext(); return rootContext();
return 0; return nullptr;
} }
QQmlContext *NodeInstanceServer::rootContext() const QQmlContext *NodeInstanceServer::rootContext() const
@@ -979,7 +971,7 @@ void NodeInstanceServer::setInstanceAuxiliaryData(const PropertyValueContainer &
} }
} }
if (auxiliaryContainer.name().endsWith("@NodeInstance")) { if (auxiliaryContainer.name().endsWith("@NodeInstance")) {
PropertyName propertyName = auxiliaryContainer.name().left(auxiliaryContainer.name().count() - 12); PropertyName propertyName = auxiliaryContainer.name().left(auxiliaryContainer.name().count() - 13);
if (!auxiliaryContainer.value().isNull()) { if (!auxiliaryContainer.value().isNull()) {
setInstancePropertyVariant(PropertyValueContainer(auxiliaryContainer.instanceId(), setInstancePropertyVariant(PropertyValueContainer(auxiliaryContainer.instanceId(),
propertyName, propertyName,

View File

@@ -71,7 +71,6 @@ public:
typedef QPair<QString, QPointer<QObject> > DummyPair; typedef QPair<QString, QPointer<QObject> > DummyPair;
explicit NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient); explicit NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient);
~NodeInstanceServer();
void createInstances(const CreateInstancesCommand &command); void createInstances(const CreateInstancesCommand &command);
void changeFileUrl(const ChangeFileUrlCommand &command); void changeFileUrl(const ChangeFileUrlCommand &command);
@@ -214,10 +213,10 @@ private:
QPointer<Internal::ChildrenChangeEventFilter> m_childrenChangeEventFilter; QPointer<Internal::ChildrenChangeEventFilter> m_childrenChangeEventFilter;
QUrl m_fileUrl; QUrl m_fileUrl;
NodeInstanceClientInterface *m_nodeInstanceClient; NodeInstanceClientInterface *m_nodeInstanceClient;
int m_timer; int m_timer = 0;
int m_renderTimerInterval; int m_renderTimerInterval = 16;
bool m_slowRenderTimer; bool m_slowRenderTimer = false;
int m_slowRenderTimerInterval; int m_slowRenderTimerInterval = 200;
QVector<InstancePropertyPair> m_changedPropertyList; QVector<InstancePropertyPair> m_changedPropertyList;
QByteArray m_importCode; QByteArray m_importCode;
QPointer<QObject> m_dummyContextObject; QPointer<QObject> m_dummyContextObject;

View File

@@ -211,7 +211,7 @@ void Lexer::scan_helper(Token *tok)
_state = 0; _state = 0;
scanCppComment(originalKind); scanCppComment(originalKind);
return; return;
} else if (isRawStringLiteral(s._tokenKind)) { } else if (!control() && isRawStringLiteral(s._tokenKind)) {
tok->f.kind = s._tokenKind; tok->f.kind = s._tokenKind;
if (scanUntilRawStringLiteralEndSimple()) if (scanUntilRawStringLiteralEndSimple())
_state = 0; _state = 0;
@@ -755,13 +755,17 @@ void Lexer::scanRawStringLiteral(Token *tok, unsigned char hint)
yyinp(); yyinp();
} else if (_yychar == ')') { } else if (_yychar == ')') {
yyinp(); yyinp();
if (delimLength == -1) if (delimLength == -1) {
break; tok->f.kind = T_ERROR;
return;
}
closingDelimCandidate = _currentChar; closingDelimCandidate = _currentChar;
} else { } else {
if (delimLength == -1) { if (delimLength == -1) {
if (_yychar == '\\' || std::isspace(_yychar)) if (_yychar == '\\' || std::isspace(_yychar)) {
break; tok->f.kind = T_ERROR;
return;
}
yyinp(); yyinp();
} else { } else {
if (!closingDelimCandidate) { if (!closingDelimCandidate) {
@@ -804,7 +808,7 @@ void Lexer::scanRawStringLiteral(Token *tok, unsigned char hint)
else else
tok->f.kind = T_RAW_STRING_LITERAL; tok->f.kind = T_RAW_STRING_LITERAL;
if (!closed) if (!control() && !closed)
s._tokenKind = tok->f.kind; s._tokenKind = tok->f.kind;
} }

View File

@@ -175,6 +175,7 @@ HEADERS += \
$$PWD/requestsourcerangesforquerymessage.h \ $$PWD/requestsourcerangesforquerymessage.h \
$$PWD/stringcachefwd.h \ $$PWD/stringcachefwd.h \
$$PWD/stringcachealgorithms.h \ $$PWD/stringcachealgorithms.h \
$$PWD/projectmanagementserverinterface.h $$PWD/projectmanagementserverinterface.h \
$$PWD/refactoringdatabaseinitializer.h
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols

View File

@@ -36,8 +36,7 @@ QDebug operator<<(QDebug debug, const FollowSymbolMessage &message)
debug.nospace() << "FollowSymbolMessage(" debug.nospace() << "FollowSymbolMessage("
<< message.m_fileContainer << message.m_fileContainer
<< ", " << message.m_ticketNumber << ", " << message.m_ticketNumber
<< ", " << message.m_sourceRange << ", " << message.m_sourceRange;
<< ", " << message.m_failedToFollow;
debug.nospace() << ")"; debug.nospace() << ")";
@@ -50,7 +49,6 @@ std::ostream &operator<<(std::ostream &os, const FollowSymbolMessage &message)
<< message.m_fileContainer << ", " << message.m_fileContainer << ", "
<< message.m_ticketNumber << ", " << message.m_ticketNumber << ", "
<< message.m_sourceRange << ", " << message.m_sourceRange << ", "
<< message.m_failedToFollow << ", "
<< ")"; << ")";
return os; return os;

View File

@@ -39,12 +39,10 @@ public:
FollowSymbolMessage() = default; FollowSymbolMessage() = default;
FollowSymbolMessage(const FileContainer &fileContainer, FollowSymbolMessage(const FileContainer &fileContainer,
const SourceRangeContainer &range, const SourceRangeContainer &range,
bool failedToFollow,
quint64 ticketNumber) quint64 ticketNumber)
: m_fileContainer(fileContainer) : m_fileContainer(fileContainer)
, m_sourceRange(range) , m_sourceRange(range)
, m_ticketNumber(ticketNumber) , m_ticketNumber(ticketNumber)
, m_failedToFollow(failedToFollow)
{ {
} }
const FileContainer &fileContainer() const const FileContainer &fileContainer() const
@@ -57,11 +55,6 @@ public:
return m_sourceRange; return m_sourceRange;
} }
bool failedToFollow() const
{
return m_failedToFollow;
}
quint64 ticketNumber() const quint64 ticketNumber() const
{ {
return m_ticketNumber; return m_ticketNumber;
@@ -72,7 +65,6 @@ public:
out << message.m_fileContainer; out << message.m_fileContainer;
out << message.m_sourceRange; out << message.m_sourceRange;
out << message.m_ticketNumber; out << message.m_ticketNumber;
out << message.m_failedToFollow;
return out; return out;
} }
@@ -81,7 +73,6 @@ public:
in >> message.m_fileContainer; in >> message.m_fileContainer;
in >> message.m_sourceRange; in >> message.m_sourceRange;
in >> message.m_ticketNumber; in >> message.m_ticketNumber;
in >> message.m_failedToFollow;
return in; return in;
} }
@@ -89,8 +80,7 @@ public:
{ {
return first.m_ticketNumber == second.m_ticketNumber return first.m_ticketNumber == second.m_ticketNumber
&& first.m_fileContainer == second.m_fileContainer && first.m_fileContainer == second.m_fileContainer
&& first.m_sourceRange == second.m_sourceRange && first.m_sourceRange == second.m_sourceRange;
&& first.m_failedToFollow == second.m_failedToFollow;
} }
friend CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FollowSymbolMessage &message); friend CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FollowSymbolMessage &message);
@@ -99,7 +89,6 @@ private:
FileContainer m_fileContainer; FileContainer m_fileContainer;
SourceRangeContainer m_sourceRange; SourceRangeContainer m_sourceRange;
quint64 m_ticketNumber = 0; quint64 m_ticketNumber = 0;
bool m_failedToFollow = false;
}; };
DECLARE_MESSAGE(FollowSymbolMessage); DECLARE_MESSAGE(FollowSymbolMessage);

View File

@@ -65,6 +65,8 @@ QDebug operator<<(QDebug debug, const HighlightingMarkContainer &container)
<< container.column() << ", " << container.column() << ", "
<< container.length() << ", " << container.length() << ", "
<< highlightingTypeToCStringLiteral(container.types().mainHighlightingType) << ", " << highlightingTypeToCStringLiteral(container.types().mainHighlightingType) << ", "
<< container.isIdentifier() << ", "
<< container.isIncludeDirectivePath()
<< ")"; << ")";
return debug; return debug;
@@ -94,7 +96,9 @@ std::ostream &operator<<(std::ostream &os, const HighlightingMarkContainer &cont
<< container.line() << ", " << container.line() << ", "
<< container.column() << ", " << container.column() << ", "
<< container.length() << ", " << container.length() << ", "
<< container.types() << container.types() << ", "
<< container.isIdentifier() << ", "
<< container.isIncludeDirectivePath()
<< ")"; << ")";
return os; return os;

View File

@@ -44,11 +44,14 @@ class HighlightingMarkContainer
{ {
public: public:
HighlightingMarkContainer() = default; HighlightingMarkContainer() = default;
HighlightingMarkContainer(uint line, uint column, uint length, HighlightingTypes types) HighlightingMarkContainer(uint line, uint column, uint length, HighlightingTypes types,
bool isIdentifier = false, bool isIncludeDirectivePath = false)
: line_(line), : line_(line),
column_(column), column_(column),
length_(length), length_(length),
types_(types) types_(types),
isIdentifier_(isIdentifier),
isIncludeDirectivePath_(isIncludeDirectivePath)
{ {
} }
@@ -80,12 +83,29 @@ public:
return types_; return types_;
} }
bool isInvalid() const
{
return line_ == 0 && column_ == 0 && length_ == 0;
}
bool isIdentifier() const
{
return isIdentifier_;
}
bool isIncludeDirectivePath() const
{
return isIncludeDirectivePath_;
}
friend QDataStream &operator<<(QDataStream &out, const HighlightingMarkContainer &container) friend QDataStream &operator<<(QDataStream &out, const HighlightingMarkContainer &container)
{ {
out << container.line_; out << container.line_;
out << container.column_; out << container.column_;
out << container.length_; out << container.length_;
out << container.types_; out << container.types_;
out << container.isIdentifier_;
out << container.isIncludeDirectivePath_;
return out; return out;
} }
@@ -96,6 +116,8 @@ public:
in >> container.column_; in >> container.column_;
in >> container.length_; in >> container.length_;
in >> container.types_; in >> container.types_;
in >> container.isIdentifier_;
in >> container.isIncludeDirectivePath_;
return in; return in;
} }
@@ -105,7 +127,9 @@ public:
return first.line_ == second.line_ return first.line_ == second.line_
&& first.column_ == second.column_ && first.column_ == second.column_
&& first.length_ == second.length_ && first.length_ == second.length_
&& first.types_ == second.types_; && first.types_ == second.types_
&& first.isIdentifier_ == second.isIdentifier_
&& first.isIncludeDirectivePath_ == second.isIncludeDirectivePath_;
} }
private: private:
@@ -113,6 +137,8 @@ private:
uint column_ = 0; uint column_ = 0;
uint length_ = 0; uint length_ = 0;
HighlightingTypes types_; HighlightingTypes types_;
bool isIdentifier_ = false;
bool isIncludeDirectivePath_ = false;
}; };
inline QDataStream &operator<<(QDataStream &out, HighlightingType highlightingType) inline QDataStream &operator<<(QDataStream &out, HighlightingType highlightingType)

View File

@@ -0,0 +1,93 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <createtablesqlstatementbuilder.h>
#include <sqlitetransaction.h>
#include <sqlitetable.h>
namespace ClangBackEnd {
template<typename DatabaseType>
class RefactoringDatabaseInitializer
{
public:
RefactoringDatabaseInitializer(DatabaseType &database)
: database(database)
{
Sqlite::ImmediateTransaction<DatabaseType> transaction{database};
createSymbolsTable();
createLocationsTable();
createSourcesTable();
transaction.commit();
}
void createSymbolsTable()
{
Sqlite::Table table;
table.setUseIfNotExists(true);
table.setName("symbols");
table.addColumn("symbolId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey);
const Sqlite::Column &usrColumn = table.addColumn("usr", Sqlite::ColumnType::Text);
table.addColumn("symbolName", Sqlite::ColumnType::Text);
table.addIndex({usrColumn});
table.initialize(database);
}
void createLocationsTable()
{
Sqlite::Table table;
table.setUseIfNotExists(true);
table.setName("locations");
table.addColumn("symbolId", Sqlite::ColumnType::Integer);
table.addColumn("line", Sqlite::ColumnType::Integer);
table.addColumn("column", Sqlite::ColumnType::Integer);
const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer);
table.addIndex({sourceIdColumn});
table.initialize(database);
}
void createSourcesTable()
{
Sqlite::Table table;
table.setUseIfNotExists(true);
table.setName("sources");
table.addColumn("sourceId", Sqlite::ColumnType::Integer, Sqlite::Contraint::PrimaryKey);
table.addColumn("sourcePath", Sqlite::ColumnType::Text);
table.initialize(database);
}
public:
DatabaseType &database;
};
} // namespace ClangBackEnd

View File

@@ -42,7 +42,6 @@ QDebug operator<<(QDebug debug, const RequestFollowSymbolMessage &message)
debug.nospace() << message.m_ticketNumber << ", "; debug.nospace() << message.m_ticketNumber << ", ";
debug.nospace() << message.m_line << ", "; debug.nospace() << message.m_line << ", ";
debug.nospace() << message.m_column << ", "; debug.nospace() << message.m_column << ", ";
debug.nospace() << message.m_resolveTarget << ", ";
debug.nospace() << ")"; debug.nospace() << ")";
@@ -57,7 +56,6 @@ std::ostream &operator<<(std::ostream &os, const RequestFollowSymbolMessage &mes
<< message.m_ticketNumber << ", " << message.m_ticketNumber << ", "
<< message.m_line << ", " << message.m_line << ", "
<< message.m_column << ", " << message.m_column << ", "
<< message.m_resolveTarget << ", "
<< ")"; << ")";
return os; return os;

View File

@@ -40,14 +40,12 @@ public:
RequestFollowSymbolMessage(const FileContainer &fileContainer, RequestFollowSymbolMessage(const FileContainer &fileContainer,
const QVector<Utf8String> &dependentFiles, const QVector<Utf8String> &dependentFiles,
quint32 line, quint32 line,
quint32 column, quint32 column)
bool resolveTarget = true)
: m_fileContainer(fileContainer) : m_fileContainer(fileContainer)
, m_ticketNumber(++ticketCounter) , m_ticketNumber(++ticketCounter)
, m_line(line) , m_line(line)
, m_column(column) , m_column(column)
, m_dependentFiles(dependentFiles) , m_dependentFiles(dependentFiles)
, m_resolveTarget(resolveTarget)
{ {
} }
@@ -71,11 +69,6 @@ public:
return m_column; return m_column;
} }
bool resolveTarget() const
{
return m_resolveTarget;
}
quint64 ticketNumber() const quint64 ticketNumber() const
{ {
return m_ticketNumber; return m_ticketNumber;
@@ -88,7 +81,6 @@ public:
out << message.m_ticketNumber; out << message.m_ticketNumber;
out << message.m_line; out << message.m_line;
out << message.m_column; out << message.m_column;
out << message.m_resolveTarget;
return out; return out;
} }
@@ -100,7 +92,6 @@ public:
in >> message.m_ticketNumber; in >> message.m_ticketNumber;
in >> message.m_line; in >> message.m_line;
in >> message.m_column; in >> message.m_column;
in >> message.m_resolveTarget;
return in; return in;
} }
@@ -112,7 +103,6 @@ public:
&& first.m_line == second.m_line && first.m_line == second.m_line
&& first.m_column == second.m_column && first.m_column == second.m_column
&& first.m_fileContainer == second.m_fileContainer && first.m_fileContainer == second.m_fileContainer
&& first.m_resolveTarget == second.m_resolveTarget
&& first.m_dependentFiles == second.m_dependentFiles; && first.m_dependentFiles == second.m_dependentFiles;
} }
@@ -124,7 +114,6 @@ private:
quint32 m_line = 0; quint32 m_line = 0;
quint32 m_column = 0; quint32 m_column = 0;
QVector<Utf8String> m_dependentFiles; QVector<Utf8String> m_dependentFiles;
bool m_resolveTarget = true;
static CMBIPC_EXPORT quint64 ticketCounter; static CMBIPC_EXPORT quint64 ticketCounter;
}; };

View File

@@ -108,16 +108,6 @@ OpenMode Database::openMode() const
return m_openMode; return m_openMode;
} }
int Database::changesCount()
{
return m_databaseBackend.changesCount();
}
int Database::totalChangesCount()
{
return m_databaseBackend.totalChangesCount();
}
void Database::execute(Utils::SmallStringView sqlStatement) void Database::execute(Utils::SmallStringView sqlStatement)
{ {
m_databaseBackend.execute(sqlStatement); m_databaseBackend.execute(sqlStatement);

View File

@@ -31,6 +31,7 @@
#include <utils/smallstring.h> #include <utils/smallstring.h>
#include <mutex>
#include <vector> #include <vector>
namespace Sqlite { namespace Sqlite {
@@ -38,11 +39,13 @@ namespace Sqlite {
class SQLITE_EXPORT Database class SQLITE_EXPORT Database
{ {
template <typename Database> template <typename Database>
friend class SqliteAbstractTransaction; friend class AbstractTransaction;
friend class SqliteStatement; friend class Statement;
friend class SqliteBackend; friend class Backend;
public: public:
using MutexType = std::mutex;
Database(); Database();
Database(Utils::PathString &&databaseFilePath); Database(Utils::PathString &&databaseFilePath);
@@ -70,21 +73,34 @@ public:
void setOpenMode(OpenMode openMode); void setOpenMode(OpenMode openMode);
OpenMode openMode() const; OpenMode openMode() const;
int changesCount();
int totalChangesCount();
void execute(Utils::SmallStringView sqlStatement); void execute(Utils::SmallStringView sqlStatement);
DatabaseBackend &backend(); DatabaseBackend &backend();
int64_t lastInsertedRowId() const
{
return m_databaseBackend.lastInsertedRowId();
}
int changesCount()
{
return m_databaseBackend.changesCount();
}
int totalChangesCount()
{
return m_databaseBackend.totalChangesCount();
}
private: private:
void initializeTables(); void initializeTables();
std::mutex &databaseMutex() { return m_databaseMutex; }
private: private:
Utils::PathString m_databaseFilePath;
DatabaseBackend m_databaseBackend; DatabaseBackend m_databaseBackend;
std::vector<Table> m_sqliteTables; std::vector<Table> m_sqliteTables;
Utils::PathString m_databaseFilePath; std::mutex m_databaseMutex;
JournalMode m_journalMode = JournalMode::Wal; JournalMode m_journalMode = JournalMode::Wal;
OpenMode m_openMode = OpenMode::ReadWrite; OpenMode m_openMode = OpenMode::ReadWrite;
bool m_isOpen = false; bool m_isOpen = false;

View File

@@ -31,6 +31,7 @@
#include "sqlitestatement.h" #include "sqlitestatement.h"
#include "sqlitewritestatement.h" #include "sqlitewritestatement.h"
#include <QFileInfo>
#include <QThread> #include <QThread>
#include <QDebug> #include <QDebug>
@@ -109,7 +110,7 @@ void DatabaseBackend::open(Utils::SmallStringView databaseFilePath, OpenMode mod
cacheTextEncoding(); cacheTextEncoding();
} }
sqlite3 *DatabaseBackend::sqliteDatabaseHandle() sqlite3 *DatabaseBackend::sqliteDatabaseHandle() const
{ {
checkDatabaseHandleIsNotNull(); checkDatabaseHandleIsNotNull();
return m_databaseHandle; return m_databaseHandle;
@@ -156,16 +157,21 @@ Utils::SmallStringVector DatabaseBackend::columnNames(Utils::SmallStringView tab
return statement.columnNames(); return statement.columnNames();
} }
int DatabaseBackend::changesCount() int DatabaseBackend::changesCount() const
{ {
return sqlite3_changes(sqliteDatabaseHandle()); return sqlite3_changes(sqliteDatabaseHandle());
} }
int DatabaseBackend::totalChangesCount() int DatabaseBackend::totalChangesCount() const
{ {
return sqlite3_total_changes(sqliteDatabaseHandle()); return sqlite3_total_changes(sqliteDatabaseHandle());
} }
int64_t DatabaseBackend::lastInsertedRowId() const
{
return sqlite3_last_insert_rowid(sqliteDatabaseHandle());
}
void DatabaseBackend::execute(Utils::SmallStringView sqlStatement) void DatabaseBackend::execute(Utils::SmallStringView sqlStatement)
{ {
ReadWriteStatement statement(sqlStatement, m_database); ReadWriteStatement statement(sqlStatement, m_database);
@@ -230,24 +236,29 @@ void DatabaseBackend::cacheTextEncoding()
void DatabaseBackend::checkForOpenDatabaseWhichCanBeClosed() void DatabaseBackend::checkForOpenDatabaseWhichCanBeClosed()
{ {
if (m_databaseHandle == nullptr) if (m_databaseHandle == nullptr)
throwException("SqliteDatabaseBackend::close: database is not open so it can not be closed."); throw DatabaseIsAlreadyClosed("SqliteDatabaseBackend::close: database is not open so it can not be closed.");
} }
void DatabaseBackend::checkDatabaseClosing(int resultCode) void DatabaseBackend::checkDatabaseClosing(int resultCode)
{ {
switch (resultCode) { switch (resultCode) {
case SQLITE_OK: return; case SQLITE_OK: return;
default: throwException("SqliteDatabaseBackend::close: unknown error happens at closing!"); case SQLITE_BUSY: throw DatabaseIsBusy("SqliteDatabaseBackend::close: database is busy because of e.g. unfinalized statements and will stay open!");
default: throwUnknowError("SqliteDatabaseBackend::close: unknown error happens at closing!");
} }
} }
void DatabaseBackend::checkCanOpenDatabase(Utils::SmallStringView databaseFilePath) void DatabaseBackend::checkCanOpenDatabase(Utils::SmallStringView databaseFilePath)
{ {
if (databaseFilePath.isEmpty()) if (databaseFilePath.isEmpty())
throw Exception("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened:", "database file path is empty!"); throw DatabaseFilePathIsEmpty("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened because the file path is empty!");
if (!QFileInfo::exists(QFileInfo(QString(databaseFilePath)).path()))
throw WrongFilePath("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened because of wrong file path!",
Utils::SmallString(databaseFilePath));
if (databaseIsOpen()) if (databaseIsOpen())
throw Exception("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened:", "database is already open!"); throw DatabaseIsAlreadyOpen("SqliteDatabaseBackend::SqliteDatabaseBackend: database cannot be opened because it is already open!");
} }
void DatabaseBackend::checkDatabaseCouldBeOpened(int resultCode) void DatabaseBackend::checkDatabaseCouldBeOpened(int resultCode)
@@ -262,16 +273,16 @@ void DatabaseBackend::checkDatabaseCouldBeOpened(int resultCode)
} }
void DatabaseBackend::checkPragmaValue(Utils::SmallStringView databaseValue, void DatabaseBackend::checkPragmaValue(Utils::SmallStringView databaseValue,
Utils::SmallStringView expectedValue) Utils::SmallStringView expectedValue)
{ {
if (databaseValue != expectedValue) if (databaseValue != expectedValue)
throwException("SqliteDatabaseBackend::setPragmaValue: pragma value is not set!"); throw PragmaValueNotSet("SqliteDatabaseBackend::setPragmaValue: pragma value is not set!");
} }
void DatabaseBackend::checkDatabaseHandleIsNotNull() void DatabaseBackend::checkDatabaseHandleIsNotNull() const
{ {
if (m_databaseHandle == nullptr) if (m_databaseHandle == nullptr)
throwException("SqliteDatabaseBackend: database is not open!"); throwDatabaseIsNotOpen("SqliteDatabaseBackend: database is not open!");
} }
void DatabaseBackend::checkIfMultithreadingIsActivated(int resultCode) void DatabaseBackend::checkIfMultithreadingIsActivated(int resultCode)
@@ -392,6 +403,16 @@ void DatabaseBackend::throwException(const char *whatHasHappens) const
throw Exception(whatHasHappens); throw Exception(whatHasHappens);
} }
void DatabaseBackend::throwUnknowError(const char *whatHasHappens) const
{
throw UnknowError(whatHasHappens);
}
void DatabaseBackend::throwDatabaseIsNotOpen(const char *whatHasHappens) const
{
throw DatabaseIsNotOpen(whatHasHappens);
}
template <typename Type> template <typename Type>
Type DatabaseBackend::toValue(Utils::SmallStringView sqlStatement) Type DatabaseBackend::toValue(Utils::SmallStringView sqlStatement)
{ {
@@ -399,7 +420,7 @@ Type DatabaseBackend::toValue(Utils::SmallStringView sqlStatement)
statement.next(); statement.next();
return statement.value<Type>(0); return statement.fetchValue<Type>(0);
} }
} // namespace Sqlite } // namespace Sqlite

View File

@@ -58,7 +58,7 @@ public:
void close(); void close();
void closeWithoutException(); void closeWithoutException();
sqlite3* sqliteDatabaseHandle(); sqlite3* sqliteDatabaseHandle() const;
void setJournalMode(JournalMode journalMode); void setJournalMode(JournalMode journalMode);
JournalMode journalMode(); JournalMode journalMode();
@@ -68,8 +68,10 @@ public:
Utils::SmallStringVector columnNames(Utils::SmallStringView tableName); Utils::SmallStringVector columnNames(Utils::SmallStringView tableName);
int changesCount(); int changesCount() const;
int totalChangesCount(); int totalChangesCount() const;
int64_t lastInsertedRowId() const;
void execute(Utils::SmallStringView sqlStatement); void execute(Utils::SmallStringView sqlStatement);
@@ -95,7 +97,7 @@ protected:
void checkCanOpenDatabase(Utils::SmallStringView databaseFilePath); void checkCanOpenDatabase(Utils::SmallStringView databaseFilePath);
void checkDatabaseCouldBeOpened(int resultCode); void checkDatabaseCouldBeOpened(int resultCode);
void checkPragmaValue(Utils::SmallStringView databaseValue, Utils::SmallStringView expectedValue); void checkPragmaValue(Utils::SmallStringView databaseValue, Utils::SmallStringView expectedValue);
void checkDatabaseHandleIsNotNull(); void checkDatabaseHandleIsNotNull() const;
void checkIfMultithreadingIsActivated(int resultCode); void checkIfMultithreadingIsActivated(int resultCode);
void checkIfLoogingIsActivated(int resultCode); void checkIfLoogingIsActivated(int resultCode);
void checkMmapSizeIsSet(int resultCode); void checkMmapSizeIsSet(int resultCode);
@@ -110,8 +112,9 @@ protected:
Q_NORETURN static void throwExceptionStatic(const char *whatHasHappens); Q_NORETURN static void throwExceptionStatic(const char *whatHasHappens);
Q_NORETURN void throwException(const char *whatHasHappens) const; [[noreturn]] void throwException(const char *whatHasHappens) const;
[[noreturn]] void throwUnknowError(const char *whatHasHappens) const;
[[noreturn]] void throwDatabaseIsNotOpen(const char *whatHasHappens) const;
private: private:
Database &m_database; Database &m_database;

View File

@@ -48,4 +48,211 @@ private:
Utils::SmallString m_sqliteErrorMessage; Utils::SmallString m_sqliteErrorMessage;
}; };
class StatementIsBusy : public Exception
{
public:
StatementIsBusy(const char *whatErrorHasHappen,
Utils::SmallString &&sqliteErrorMessage = Utils::SmallString())
: Exception(whatErrorHasHappen, std::move(sqliteErrorMessage))
{
}
};
class DatabaseIsBusy : public Exception
{
public:
DatabaseIsBusy(const char *whatErrorHasHappen)
: Exception(whatErrorHasHappen)
{
}
};
class StatementHasError : public Exception
{
public:
StatementHasError(const char *whatErrorHasHappen,
Utils::SmallString &&sqliteErrorMessage = Utils::SmallString())
: Exception(whatErrorHasHappen, std::move(sqliteErrorMessage))
{
}
};
class StatementIsMisused : public Exception
{
public:
StatementIsMisused(const char *whatErrorHasHappen,
Utils::SmallString &&sqliteErrorMessage = Utils::SmallString())
: Exception(whatErrorHasHappen, std::move(sqliteErrorMessage))
{
}
};
class ContraintPreventsModification : public Exception
{
public:
ContraintPreventsModification(const char *whatErrorHasHappen,
Utils::SmallString &&sqliteErrorMessage = Utils::SmallString())
: Exception(whatErrorHasHappen, std::move(sqliteErrorMessage))
{
}
};
class NoValuesToFetch : public Exception
{
public:
NoValuesToFetch(const char *whatErrorHasHappen)
: Exception(whatErrorHasHappen)
{
}
};
class InvalidColumnFetched : public Exception
{
public:
InvalidColumnFetched(const char *whatErrorHasHappen)
: Exception(whatErrorHasHappen)
{
}
};
class BindingIndexIsOutOfRange : public Exception
{
public:
BindingIndexIsOutOfRange(const char *whatErrorHasHappen,
Utils::SmallString &&sqliteErrorMessage = Utils::SmallString())
: Exception(whatErrorHasHappen, std::move(sqliteErrorMessage))
{
}
};
class WrongBingingName : public Exception
{
public:
WrongBingingName(const char *whatErrorHasHappen)
: Exception(whatErrorHasHappen)
{
}
};
class DatabaseIsNotOpen : public Exception
{
public:
DatabaseIsNotOpen(const char *whatErrorHasHappen)
: Exception(whatErrorHasHappen)
{
}
};
class DatabaseCannotBeOpened : public Exception
{
public:
DatabaseCannotBeOpened(const char *whatErrorHasHappen,
Utils::SmallString &&errorMessage = Utils::SmallString())
: Exception(whatErrorHasHappen, std::move(errorMessage))
{
}
};
class DatabaseFilePathIsEmpty : public DatabaseCannotBeOpened
{
public:
DatabaseFilePathIsEmpty(const char *whatErrorHasHappen)
: DatabaseCannotBeOpened(whatErrorHasHappen)
{
}
};
class DatabaseIsAlreadyOpen : public DatabaseCannotBeOpened
{
public:
DatabaseIsAlreadyOpen(const char *whatErrorHasHappen)
: DatabaseCannotBeOpened(whatErrorHasHappen)
{
}
};
class DatabaseCannotBeClosed : public Exception
{
public:
DatabaseCannotBeClosed(const char *whatErrorHasHappen)
: Exception(whatErrorHasHappen)
{
}
};
class DatabaseIsAlreadyClosed : public DatabaseCannotBeClosed
{
public:
DatabaseIsAlreadyClosed(const char *whatErrorHasHappen)
: DatabaseCannotBeClosed(whatErrorHasHappen)
{
}
};
class WrongFilePath : public DatabaseCannotBeOpened
{
public:
WrongFilePath(const char *whatErrorHasHappen,
Utils::SmallString &&errorMessage = Utils::SmallString())
: DatabaseCannotBeOpened(whatErrorHasHappen, std::move(errorMessage))
{
}
};
class PragmaValueNotSet : public Exception
{
public:
PragmaValueNotSet(const char *whatErrorHasHappen)
: Exception(whatErrorHasHappen)
{
}
};
class NotReadOnlySqlStatement : public Exception
{
public:
NotReadOnlySqlStatement(const char *whatErrorHasHappen)
: Exception(whatErrorHasHappen)
{
}
};
class NotWriteSqlStatement : public Exception
{
public:
NotWriteSqlStatement(const char *whatErrorHasHappen)
: Exception(whatErrorHasHappen)
{
}
};
class DeadLock : public Exception
{
public:
DeadLock(const char *whatErrorHasHappen)
: Exception(whatErrorHasHappen)
{
}
};
class UnknowError : public Exception
{
public:
UnknowError(const char *whatErrorHasHappen,
Utils::SmallString &&errorMessage = Utils::SmallString())
: Exception(whatErrorHasHappen, std::move(errorMessage))
{
}
};
class BindingTooBig : public Exception
{
public:
BindingTooBig(const char *whatErrorHasHappen,
Utils::SmallString &&errorMessage = Utils::SmallString())
: Exception(whatErrorHasHappen, std::move(errorMessage))
{
}
};
} // namespace Sqlite } // namespace Sqlite

View File

@@ -39,7 +39,7 @@ ReadStatement::ReadStatement(Utils::SmallStringView sqlStatement,
void ReadStatement::checkIsReadOnlyStatement() void ReadStatement::checkIsReadOnlyStatement()
{ {
if (!isReadOnlyStatement()) if (!isReadOnlyStatement())
throwException("SqliteStatement::SqliteReadStatement: is not read only statement!"); throw NotReadOnlySqlStatement("SqliteStatement::SqliteReadStatement: is not read only statement!");
} }
} // namespace Sqlite } // namespace Sqlite

View File

@@ -34,21 +34,8 @@ class SQLITE_EXPORT ReadStatement final : private Statement
public: public:
explicit ReadStatement(Utils::SmallStringView sqlStatement, Database &database); explicit ReadStatement(Utils::SmallStringView sqlStatement, Database &database);
using Statement::next;
using Statement::reset;
using Statement::value; using Statement::value;
using Statement::structValues;
using Statement::tupleValues;
using Statement::text;
using Statement::values; using Statement::values;
using Statement::columnCount;
using Statement::columnNames;
using Statement::bind;
using Statement::bindValues;
using Statement::bindNameValues;
using Statement::bindingIndexForName;
using Statement::setBindingColumnNames;
using Statement::bindingColumnNames;
using Statement::toValue; using Statement::toValue;
using Statement::database; using Statement::database;

View File

@@ -36,22 +36,9 @@ class SQLITE_EXPORT ReadWriteStatement final : private Statement
public: public:
ReadWriteStatement(Utils::SmallStringView sqlStatement, Database &database); ReadWriteStatement(Utils::SmallStringView sqlStatement, Database &database);
using Statement::next;
using Statement::execute; using Statement::execute;
using Statement::reset;
using Statement::bind;
using Statement::bindValues;
using Statement::bindNameValues;
using Statement::bindingIndexForName;
using Statement::setBindingColumnNames;
using Statement::bindingColumnNames;
using Statement::value; using Statement::value;
using Statement::text;
using Statement::values; using Statement::values;
using Statement::structValues;
using Statement::tupleValues;
using Statement::columnCount;
using Statement::columnNames;
using Statement::toValue; using Statement::toValue;
using Statement::database; using Statement::database;
using Statement::write; using Statement::write;

View File

@@ -95,19 +95,26 @@ private:
void Statement::waitForUnlockNotify() const void Statement::waitForUnlockNotify() const
{ {
UnlockNotification unlockNotification; UnlockNotification unlockNotification;
int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(), UnlockNotification::unlockNotifyCallBack, &unlockNotification); int resultCode = sqlite3_unlock_notify(sqliteDatabaseHandle(),
UnlockNotification::unlockNotifyCallBack,
&unlockNotification);
if (resultCode == SQLITE_OK) if (resultCode == SQLITE_LOCKED)
unlockNotification.wait(); throw DeadLock("SqliteStatement::waitForUnlockNotify: database is in a dead lock!");
else
throwException("SqliteStatement::waitForUnlockNotify: database is in a dead lock!"); unlockNotification.wait();
} }
void Statement::reset() const void Statement::reset() const
{ {
int resultCode = sqlite3_reset(m_compiledStatement.get()); int resultCode = sqlite3_reset(m_compiledStatement.get());
if (resultCode != SQLITE_OK) switch (resultCode) {
throwException("SqliteStatement::reset: can't reset statement!"); case SQLITE_OK: return;
case SQLITE_BUSY: throwStatementIsBusy("SqliteStatement::stepStatement: database engine was unable to acquire the database locks!");
case SQLITE_ERROR : throwStatementHasError("SqliteStatement::stepStatement: run-time error (such as a constraint violation) has occurred!");
case SQLITE_MISUSE: throwStatementIsMisused("SqliteStatement::stepStatement: was called inappropriately!");
case SQLITE_CONSTRAINT: throwConstraintPreventsModification("SqliteStatement::stepStatement: contraint prevent insert or update!");
}
m_isReadyToFetchValues = false; m_isReadyToFetchValues = false;
} }
@@ -159,30 +166,30 @@ Utils::SmallStringVector Statement::columnNames() const
void Statement::bind(int index, int value) void Statement::bind(int index, int value)
{ {
int resultCode = sqlite3_bind_int(m_compiledStatement.get(), index, value); int resultCode = sqlite3_bind_int(m_compiledStatement.get(), index, value);
if (resultCode != SQLITE_OK) checkForBindingError(resultCode);
throwException("SqliteStatement::bind: cant' bind 32 bit integer!");
} }
void Statement::bind(int index, long long value) void Statement::bind(int index, long long value)
{ {
int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value); int resultCode = sqlite3_bind_int64(m_compiledStatement.get(), index, value);
if (resultCode != SQLITE_OK) checkForBindingError(resultCode);
throwException("SqliteStatement::bind: cant' bind 64 bit integer!");
} }
void Statement::bind(int index, double value) void Statement::bind(int index, double value)
{ {
int resultCode = sqlite3_bind_double(m_compiledStatement.get(), index, value); int resultCode = sqlite3_bind_double(m_compiledStatement.get(), index, value);
if (resultCode != SQLITE_OK) checkForBindingError(resultCode);
throwException("SqliteStatement::bind: cant' bind double!");
} }
void Statement::bind(int index, Utils::SmallStringView text) void Statement::bind(int index, Utils::SmallStringView text)
{ {
int resultCode = sqlite3_bind_text(m_compiledStatement.get(), index, text.data(), int(text.size()), SQLITE_TRANSIENT); int resultCode = sqlite3_bind_text(m_compiledStatement.get(),
if (resultCode != SQLITE_OK) index,
throwException("SqliteStatement::bind: cant' bind double!"); text.data(),
int(text.size()),
SQLITE_STATIC);
checkForBindingError(resultCode);
} }
template <typename Type> template <typename Type>
@@ -250,13 +257,13 @@ bool Statement::checkForStepError(int resultCode) const
switch (resultCode) { switch (resultCode) {
case SQLITE_ROW: return true; case SQLITE_ROW: return true;
case SQLITE_DONE: return false; case SQLITE_DONE: return false;
case SQLITE_BUSY: throwException("SqliteStatement::stepStatement: database engine was unable to acquire the database locks!"); case SQLITE_BUSY: throwStatementIsBusy("SqliteStatement::stepStatement: database engine was unable to acquire the database locks!");
case SQLITE_ERROR : throwException("SqliteStatement::stepStatement: run-time error (such as a constraint violation) has occurred!"); case SQLITE_ERROR : throwStatementHasError("SqliteStatement::stepStatement: run-time error (such as a constraint violation) has occurred!");
case SQLITE_MISUSE: throwException("SqliteStatement::stepStatement: was called inappropriately!"); case SQLITE_MISUSE: throwStatementIsMisused("SqliteStatement::stepStatement: was called inappropriately!");
case SQLITE_CONSTRAINT: throwException("SqliteStatement::stepStatement: contraint prevent insert or update!"); case SQLITE_CONSTRAINT: throwConstraintPreventsModification("SqliteStatement::stepStatement: contraint prevent insert or update!");
} }
throwException("SqliteStatement::stepStatement: unknown error has happened"); throwUnknowError("SqliteStatement::stepStatement: unknown error has happened");
Q_UNREACHABLE(); Q_UNREACHABLE();
} }
@@ -265,12 +272,24 @@ void Statement::checkForPrepareError(int resultCode) const
{ {
switch (resultCode) { switch (resultCode) {
case SQLITE_OK: return; case SQLITE_OK: return;
case SQLITE_BUSY: throwException("SqliteStatement::prepareStatement: database engine was unable to acquire the database locks!"); case SQLITE_BUSY: throwStatementIsBusy("SqliteStatement::prepareStatement: database engine was unable to acquire the database locks!");
case SQLITE_ERROR : throwException("SqliteStatement::prepareStatement: run-time error (such as a constraint violation) has occurred!"); case SQLITE_ERROR : throwStatementHasError("SqliteStatement::prepareStatement: run-time error (such as a constraint violation) has occurred!");
case SQLITE_MISUSE: throwException("SqliteStatement::prepareStatement: was called inappropriately!"); case SQLITE_MISUSE: throwStatementIsMisused("SqliteStatement::prepareStatement: was called inappropriately!");
} }
throwException("SqliteStatement::prepareStatement: unknown error has happened"); throwUnknowError("SqliteStatement::prepareStatement: unknown error has happened");
}
void Statement::checkForBindingError(int resultCode) const
{
switch (resultCode) {
case SQLITE_OK: return;
case SQLITE_TOOBIG: throwBingingTooBig("SqliteStatement::bind: string or blob are over size limits(SQLITE_LIMIT_LENGTH)!");
case SQLITE_RANGE : throwBindingIndexIsOutOfRange("SqliteStatement::bind: binding index is out of range!");
case SQLITE_NOMEM: throw std::bad_alloc();
}
throwUnknowError("SqliteStatement::bind: unknown error has happened");
} }
void Statement::setIfIsReadyToFetchValues(int resultCode) const void Statement::setIfIsReadyToFetchValues(int resultCode) const
@@ -285,33 +304,27 @@ void Statement::setIfIsReadyToFetchValues(int resultCode) const
void Statement::checkIfIsReadyToFetchValues() const void Statement::checkIfIsReadyToFetchValues() const
{ {
if (!m_isReadyToFetchValues) if (!m_isReadyToFetchValues)
throwException("SqliteStatement::value: there are no values to fetch!"); throwNoValuesToFetch("SqliteStatement::value: there are no values to fetch!");
} }
void Statement::checkColumnsAreValid(const std::vector<int> &columns) const void Statement::checkColumnsAreValid(const std::vector<int> &columns) const
{ {
for (int column : columns) { for (int column : columns) {
if (column < 0 || column >= m_columnCount) if (column < 0 || column >= m_columnCount)
throwException("SqliteStatement::values: column index out of bound!"); throwInvalidColumnFetched("SqliteStatement::values: column index out of bound!");
} }
} }
void Statement::checkColumnIsValid(int column) const void Statement::checkColumnIsValid(int column) const
{ {
if (column < 0 || column >= m_columnCount) if (column < 0 || column >= m_columnCount)
throwException("SqliteStatement::values: column index out of bound!"); throwInvalidColumnFetched("SqliteStatement::values: column index out of bound!");
}
void Statement::checkBindingIndex(int index) const
{
if (index <= 0 || index > m_bindingParameterCount)
throwException("SqliteStatement::bind: binding index is out of bound!");
} }
void Statement::checkBindingName(int index) const void Statement::checkBindingName(int index) const
{ {
if (index <= 0 || index > m_bindingParameterCount) if (index <= 0 || index > m_bindingParameterCount)
throwException("SqliteStatement::bind: binding name are not exists in this statement!"); throwWrongBingingName("SqliteStatement::bind: binding name are not exists in this statement!");
} }
void Statement::setBindingParameterCount() void Statement::setBindingParameterCount()
@@ -345,9 +358,57 @@ bool Statement::isReadOnlyStatement() const
return sqlite3_stmt_readonly(m_compiledStatement.get()); return sqlite3_stmt_readonly(m_compiledStatement.get());
} }
void Statement::throwException(const char *whatHasHappened) const void Statement::throwStatementIsBusy(const char *whatHasHappened) const
{ {
throw Exception(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle())); throw StatementIsBusy(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
}
void Statement::throwStatementHasError(const char *whatHasHappened) const
{
throw StatementHasError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
}
void Statement::throwStatementIsMisused(const char *whatHasHappened) const
{
throw StatementIsMisused(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
}
void Statement::throwConstraintPreventsModification(const char *whatHasHappened) const
{
throw ContraintPreventsModification(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
}
void Statement::throwNoValuesToFetch(const char *whatHasHappened) const
{
throw NoValuesToFetch(whatHasHappened);
}
void Statement::throwInvalidColumnFetched(const char *whatHasHappened) const
{
throw InvalidColumnFetched(whatHasHappened);
}
void Statement::throwBindingIndexIsOutOfRange(const char *whatHasHappened) const
{
throw BindingIndexIsOutOfRange(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
}
void Statement::throwWrongBingingName(const char *whatHasHappened) const
{
throw WrongBingingName(whatHasHappened);
}
void Statement::throwUnknowError(const char *whatHasHappened) const
{
if (sqliteDatabaseHandle())
throw UnknowError(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
else
throw UnknowError(whatHasHappened);
}
void Statement::throwBingingTooBig(const char *whatHasHappened) const
{
throw BindingTooBig(whatHasHappened, sqlite3_errmsg(sqliteDatabaseHandle()));
} }
QString Statement::columnName(int column) const QString Statement::columnName(int column) const
@@ -384,8 +445,7 @@ static StringType convertToTextForColumn(sqlite3_stmt *sqlStatment, int column)
Q_UNREACHABLE(); Q_UNREACHABLE();
} }
template<> int Statement::fetchIntValue(int column) const
int Statement::value<int>(int column) const
{ {
checkIfIsReadyToFetchValues(); checkIfIsReadyToFetchValues();
checkColumnIsValid(column); checkColumnIsValid(column);
@@ -393,13 +453,23 @@ int Statement::value<int>(int column) const
} }
template<> template<>
long Statement::value<long>(int column) const int Statement::fetchValue<int>(int column) const
{ {
return long(value<long long>(column)); return fetchIntValue(column);
}
long Statement::fetchLongValue(int column) const
{
return long(fetchValue<long long>(column));
} }
template<> template<>
long long Statement::value<long long>(int column) const long Statement::fetchValue<long>(int column) const
{
return fetchLongValue(column);
}
long long Statement::fetchLongLongValue(int column) const
{ {
checkIfIsReadyToFetchValues(); checkIfIsReadyToFetchValues();
checkColumnIsValid(column); checkColumnIsValid(column);
@@ -407,27 +477,48 @@ long long Statement::value<long long>(int column) const
} }
template<> template<>
double Statement::value<double>(int column) const long long Statement::fetchValue<long long>(int column) const
{
return fetchLongLongValue(column);
}
double Statement::fetchDoubleValue(int column) const
{ {
checkIfIsReadyToFetchValues(); checkIfIsReadyToFetchValues();
checkColumnIsValid(column); checkColumnIsValid(column);
return sqlite3_column_double(m_compiledStatement.get(), column); return sqlite3_column_double(m_compiledStatement.get(), column);
} }
template<>
double Statement::fetchValue<double>(int column) const
{
return fetchDoubleValue(column);
}
template<typename StringType> template<typename StringType>
StringType Statement::value(int column) const StringType Statement::fetchValue(int column) const
{ {
checkIfIsReadyToFetchValues(); checkIfIsReadyToFetchValues();
checkColumnIsValid(column); checkColumnIsValid(column);
return convertToTextForColumn<StringType>(m_compiledStatement.get(), column); return convertToTextForColumn<StringType>(m_compiledStatement.get(), column);
} }
template SQLITE_EXPORT Utils::SmallString Statement::value<Utils::SmallString>(int column) const; Utils::SmallString Statement::fetchSmallStringValue(int column) const
template SQLITE_EXPORT Utils::PathString Statement::value<Utils::PathString>(int column) const; {
return fetchValue<Utils::SmallString>(column);
}
Utils::PathString Statement::fetchPathStringValue(int column) const
{
return fetchValue<Utils::PathString>(column);
}
template SQLITE_EXPORT Utils::SmallString Statement::fetchValue<Utils::SmallString>(int column) const;
template SQLITE_EXPORT Utils::PathString Statement::fetchValue<Utils::PathString>(int column) const;
Utils::SmallString Statement::text(int column) const Utils::SmallString Statement::text(int column) const
{ {
return value<Utils::SmallString>(column); return fetchValue<Utils::SmallString>(column);
} }
template <typename ContainerType> template <typename ContainerType>
@@ -437,7 +528,7 @@ ContainerType Statement::columnValues(const std::vector<int> &columnIndices) con
ContainerType valueContainer; ContainerType valueContainer;
valueContainer.reserve(columnIndices.size()); valueContainer.reserve(columnIndices.size());
for (int columnIndex : columnIndices) for (int columnIndex : columnIndices)
valueContainer.push_back(value<ElementType>(columnIndex)); valueContainer.push_back(fetchValue<ElementType>(columnIndex));
return valueContainer; return valueContainer;
} }
@@ -449,7 +540,7 @@ Type Statement::toValue(Utils::SmallStringView sqlStatement, Database &database)
statement.next(); statement.next();
return statement.value<Type>(0); return statement.fetchValue<Type>(0);
} }
template SQLITE_EXPORT int Statement::toValue<int>(Utils::SmallStringView sqlStatement, Database &database); template SQLITE_EXPORT int Statement::toValue<int>(Utils::SmallStringView sqlStatement, Database &database);

View File

@@ -31,6 +31,8 @@
#include <utils/smallstringvector.h> #include <utils/smallstringvector.h>
#include <utils/optional.h>
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <type_traits> #include <type_traits>
@@ -58,16 +60,22 @@ protected:
void execute() const; void execute() const;
void reset() const; void reset() const;
int fetchIntValue(int column) const;
long fetchLongValue(int column) const;
long long fetchLongLongValue(int column) const;
double fetchDoubleValue(int column) const;
Utils::SmallString fetchSmallStringValue(int column) const;
Utils::PathString fetchPathStringValue(int column) const;
template<typename Type> template<typename Type>
Type value(int column) const; Type fetchValue(int column) const;
Utils::SmallString text(int column) const; Utils::SmallString text(int column) const;
int columnCount() const; int columnCount() const;
Utils::SmallStringVector columnNames() const; Utils::SmallStringVector columnNames() const;
void bind(int index, int value); void bind(int index, int fetchValue);
void bind(int index, long long value); void bind(int index, long long fetchValue);
void bind(int index, double value); void bind(int index, double fetchValue);
void bind(int index, Utils::SmallStringView value); void bind(int index, Utils::SmallStringView fetchValue);
void bind(int index, uint value) void bind(int index, uint value)
{ {
@@ -84,164 +92,86 @@ protected:
} }
template<typename... ValueType> template<typename... ValueType>
void bindValues(ValueType... values) void bindValues(const ValueType&... values)
{ {
bindValuesByIndex(1, values...); bindValuesByIndex(1, values...);
} }
template<typename... ValueType> template<typename... ValueType>
void write(ValueType... values) void write(const ValueType&... values)
{ {
bindValuesByIndex(1, values...); bindValuesByIndex(1, values...);
execute(); execute();
} }
template<typename... ValueType> template<typename... ValueType>
void bindNameValues(ValueType... values) void bindNameValues(const ValueType&... values)
{ {
bindValuesByName(values...); bindValuesByName(values...);
} }
template<typename... ValueType> template<typename... ValueType>
void writeNamed(ValueType... values) void writeNamed(const ValueType&... values)
{ {
bindValuesByName(values...); bindValuesByName(values...);
execute(); execute();
} }
template <typename Type> template <typename Type>
void bind(Utils::SmallStringView name, Type value); void bind(Utils::SmallStringView name, Type fetchValue);
int bindingIndexForName(Utils::SmallStringView name) const; int bindingIndexForName(Utils::SmallStringView name) const;
void setBindingColumnNames(const Utils::SmallStringVector &bindingColumnNames); void setBindingColumnNames(const Utils::SmallStringVector &bindingColumnNames);
const Utils::SmallStringVector &bindingColumnNames() const; const Utils::SmallStringVector &bindingColumnNames() const;
template <typename... ResultTypes> template <typename ResultType,
std::vector<std::tuple<ResultTypes...>> tupleValues(std::size_t reserveSize) int ResultTypeCount = 1>
std::vector<ResultType> values(std::size_t reserveSize)
{ {
using Container = std::vector<std::tuple<ResultTypes...>>; std::vector<ResultType> resultValues;
Container resultValues;
resultValues.reserve(reserveSize); resultValues.reserve(reserveSize);
while (next()) while (next())
emplaceTupleValues<Container, ResultTypes...>(resultValues); emplaceBackValues<ResultTypeCount>(resultValues);
reset(); reset();
return resultValues; return resultValues;
} }
template <typename... ResultTypes, template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryTypes> typename... QueryTypes>
std::vector<std::tuple<ResultTypes...>> tupleValues(std::size_t reserveSize, const QueryTypes&... queryValues) std::vector<ResultType> values(std::size_t reserveSize, const QueryTypes&... queryValues)
{ {
using Container = std::vector<std::tuple<ResultTypes...>>; std::vector<ResultType> resultValues;
Container resultValues;
resultValues.reserve(reserveSize); resultValues.reserve(reserveSize);
bindValues(queryValues...); bindValues(queryValues...);
while (next()) while (next())
emplaceTupleValues<Container, ResultTypes...>(resultValues); emplaceBackValues<ResultTypeCount>(resultValues);
reset(); reset();
return resultValues; return resultValues;
} }
template <typename... ResultTypes, template <typename ResultType,
typename... QueryElementTypes> int ResultTypeCount = 1,
std::vector<std::tuple<ResultTypes...>> tupleValues(std::size_t reserveSize,
const std::vector<std::tuple<QueryElementTypes...>> &queryTuples)
{
using Container = std::vector<std::tuple<ResultTypes...>>;
Container resultValues;
resultValues.reserve(reserveSize);
for (const auto &queryTuple : queryTuples) {
bindTupleValues(queryTuple);
while (next())
emplaceTupleValues<Container, ResultTypes...>(resultValues);
reset();
}
return resultValues;
}
template <typename... ResultTypes,
typename QueryElementType> typename QueryElementType>
std::vector<std::tuple<ResultTypes...>> tupleValues(std::size_t reserveSize, std::vector<ResultType> values(std::size_t reserveSize,
const std::vector<QueryElementType> &queryValues)
{
using Container = std::vector<std::tuple<ResultTypes...>>;
Container resultValues;
resultValues.reserve(reserveSize);
for (const QueryElementType &queryValue : queryValues) {
bindValues(queryValue);
while (next())
emplaceTupleValues<Container, ResultTypes...>(resultValues);
reset();
}
return resultValues;
}
template <typename ResultType,
typename... ResultEntryTypes>
std::vector<ResultType> structValues(std::size_t reserveSize)
{
using Container = std::vector<ResultType>;
Container resultValues;
resultValues.reserve(reserveSize);
while (next())
pushBackStructValues<Container, ResultEntryTypes...>(resultValues);
reset();
return resultValues;
}
template <typename ResultType,
typename... ResultEntryTypes,
typename... QueryTypes>
std::vector<ResultType> structValues(std::size_t reserveSize, const QueryTypes&... queryValues)
{
using Container = std::vector<ResultType>;
Container resultValues;
resultValues.reserve(reserveSize);
bindValues(queryValues...);
while (next())
pushBackStructValues<Container, ResultEntryTypes...>(resultValues);
reset();
return resultValues;
}
template <typename ResultType,
typename... ResultEntryTypes,
typename QueryElementType>
std::vector<ResultType> structValues(std::size_t reserveSize,
const std::vector<QueryElementType> &queryValues) const std::vector<QueryElementType> &queryValues)
{ {
using Container = std::vector<ResultType>; std::vector<ResultType> resultValues;
Container resultValues;
resultValues.reserve(reserveSize); resultValues.reserve(reserveSize);
for (const QueryElementType &queryValue : queryValues) { for (const QueryElementType &queryValue : queryValues) {
bindValues(queryValue); bindValues(queryValue);
while (next()) while (next())
pushBackStructValues<Container, ResultEntryTypes...>(resultValues); emplaceBackValues<ResultTypeCount>(resultValues);
reset(); reset();
} }
@@ -250,9 +180,9 @@ protected:
} }
template <typename ResultType, template <typename ResultType,
typename... ResultEntryTypes, int ResultTypeCount = 1,
typename... QueryElementTypes> typename... QueryElementTypes>
std::vector<ResultType> structValues(std::size_t reserveSize, std::vector<ResultType> values(std::size_t reserveSize,
const std::vector<std::tuple<QueryElementTypes...>> &queryTuples) const std::vector<std::tuple<QueryElementTypes...>> &queryTuples)
{ {
using Container = std::vector<ResultType>; using Container = std::vector<ResultType>;
@@ -263,62 +193,7 @@ protected:
bindTupleValues(queryTuple); bindTupleValues(queryTuple);
while (next()) while (next())
pushBackStructValues<Container, ResultEntryTypes...>(resultValues); emplaceBackValues<ResultTypeCount>(resultValues);
reset();
}
return resultValues;
}
template <typename ResultType,
typename... ElementTypes>
std::vector<ResultType> values(std::size_t reserveSize)
{
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
while (next())
resultValues.push_back(value<ResultType>(0));
reset();
return resultValues;
}
template <typename ResultType,
typename... ElementType>
std::vector<ResultType> values(std::size_t reserveSize,
const std::vector<std::tuple<ElementType...>> &queryTuples)
{
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
for (const auto &queryTuple : queryTuples) {
bindTupleValues(queryTuple);
while (next())
resultValues.push_back(value<ResultType>(0));
reset();
}
return resultValues;
}
template <typename ResultType,
typename ElementType>
std::vector<ResultType> values(std::size_t reserveSize,
const std::vector<ElementType> &queryValues)
{
std::vector<ResultType> resultValues;
resultValues.reserve(reserveSize);
for (const ElementType &queryValue : queryValues) {
bindValues(queryValue);
while (next())
resultValues.push_back(value<ResultType>(0));
reset(); reset();
} }
@@ -327,20 +202,20 @@ protected:
} }
template <typename ResultType, template <typename ResultType,
int ResultTypeCount = 1,
typename... QueryTypes> typename... QueryTypes>
std::vector<ResultType> values(std::size_t reserveSize, const QueryTypes&... queryValues) Utils::optional<ResultType> value( const QueryTypes&... queryValues)
{ {
std::vector<ResultType> resultValues; Utils::optional<ResultType> resultValue;
resultValues.reserve(reserveSize);
bindValues(queryValues...); bindValues(queryValues...);
while (next()) if (next())
resultValues.push_back(value<ResultType>(0)); resultValue = assignValue<Utils::optional<ResultType>, ResultTypeCount>();
reset(); reset();
return resultValues; return resultValue;
} }
template <typename Type> template <typename Type>
@@ -352,20 +227,28 @@ protected:
sqlite3 *sqliteDatabaseHandle() const; sqlite3 *sqliteDatabaseHandle() const;
TextEncoding databaseTextEncoding(); TextEncoding databaseTextEncoding();
bool checkForStepError(int resultCode) const; bool checkForStepError(int resultCode) const;
void checkForPrepareError(int resultCode) const; void checkForPrepareError(int resultCode) const;
void checkForBindingError(int resultCode) const;
void setIfIsReadyToFetchValues(int resultCode) const; void setIfIsReadyToFetchValues(int resultCode) const;
void checkIfIsReadyToFetchValues() const; void checkIfIsReadyToFetchValues() const;
void checkColumnsAreValid(const std::vector<int> &columns) const; void checkColumnsAreValid(const std::vector<int> &columns) const;
void checkColumnIsValid(int column) const; void checkColumnIsValid(int column) const;
void checkBindingIndex(int index) const;
void checkBindingName(int index) const; void checkBindingName(int index) const;
void setBindingParameterCount(); void setBindingParameterCount();
void setBindingColumnNamesFromStatement(); void setBindingColumnNamesFromStatement();
void setColumnCount(); void setColumnCount();
bool isReadOnlyStatement() const; bool isReadOnlyStatement() const;
Q_NORETURN void throwException(const char *whatHasHappened) const; [[noreturn]] void throwStatementIsBusy(const char *whatHasHappened) const;
[[noreturn]] void throwStatementHasError(const char *whatHasHappened) const;
[[noreturn]] void throwStatementIsMisused(const char *whatHasHappened) const;
[[noreturn]] void throwConstraintPreventsModification(const char *whatHasHappened) const;
[[noreturn]] void throwNoValuesToFetch(const char *whatHasHappened) const;
[[noreturn]] void throwInvalidColumnFetched(const char *whatHasHappened) const;
[[noreturn]] void throwBindingIndexIsOutOfRange(const char *whatHasHappened) const;
[[noreturn]] void throwWrongBingingName(const char *whatHasHappened) const;
[[noreturn]] void throwUnknowError(const char *whatHasHappened) const;
[[noreturn]] void throwBingingTooBig(const char *whatHasHappened) const;
template <typename ContainerType> template <typename ContainerType>
ContainerType columnValues(const std::vector<int> &columnIndices) const; ContainerType columnValues(const std::vector<int> &columnIndices) const;
@@ -379,58 +262,97 @@ protected:
DatabaseBackend &databaseBackend); DatabaseBackend &databaseBackend);
private: private:
class ValueGetter
{
public:
ValueGetter(Statement &statement, int column)
: statement(statement),
column(column)
{}
operator int()
{
return statement.fetchIntValue(column);
}
operator long()
{
return statement.fetchLongValue(column);
}
operator long long()
{
return statement.fetchLongLongValue(column);
}
operator double()
{
return statement.fetchDoubleValue(column);
}
operator Utils::SmallString()
{
return statement.fetchSmallStringValue(column);
}
operator Utils::PathString()
{
return statement.fetchPathStringValue(column);
}
Statement &statement;
int column;
};
template <typename ContainerType, template <typename ContainerType,
typename... ResultTypes,
int... ColumnIndices> int... ColumnIndices>
void emplaceTupleValues(ContainerType &container, std::integer_sequence<int, ColumnIndices...>) void emplaceBackValues(ContainerType &container, std::integer_sequence<int, ColumnIndices...>)
{ {
container.emplace_back(value<ResultTypes>(ColumnIndices)...); container.emplace_back(ValueGetter(*this, ColumnIndices)...);
} }
template <typename ContainerType, template <int ResultTypeCount,
typename... ResultTypes> typename ContainerType>
void emplaceTupleValues(ContainerType &container) void emplaceBackValues(ContainerType &container)
{ {
emplaceTupleValues<ContainerType, ResultTypes...>(container, std::make_integer_sequence<int, sizeof...(ResultTypes)>{}); emplaceBackValues(container, std::make_integer_sequence<int, ResultTypeCount>{});
} }
template <typename ContainerType, template <typename ResultOptionalType,
typename... ResultEntryTypes,
int... ColumnIndices> int... ColumnIndices>
void pushBackStructValues(ContainerType &container, std::integer_sequence<int, ColumnIndices...>) ResultOptionalType assignValue(std::integer_sequence<int, ColumnIndices...>)
{ {
using ResultType = typename ContainerType::value_type; return ResultOptionalType(Utils::in_place, ValueGetter(*this, ColumnIndices)...);
container.push_back(ResultType{value<ResultEntryTypes>(ColumnIndices)...});
} }
template <typename ContainerType, template <typename ResultOptionalType,
typename... ResultEntryTypes> int ResultTypeCount>
void pushBackStructValues(ContainerType &container) ResultOptionalType assignValue()
{ {
pushBackStructValues<ContainerType, ResultEntryTypes...>(container, std::make_integer_sequence<int, sizeof...(ResultEntryTypes)>{}); return assignValue<ResultOptionalType>(std::make_integer_sequence<int, ResultTypeCount>{});
} }
template<typename ValueType> template<typename ValueType>
void bindValuesByIndex(int index, ValueType value) void bindValuesByIndex(int index, const ValueType &value)
{ {
bind(index, value); bind(index, value);
} }
template<typename ValueType, typename... ValueTypes> template<typename ValueType, typename... ValueTypes>
void bindValuesByIndex(int index, ValueType value, ValueTypes... values) void bindValuesByIndex(int index, const ValueType &value, const ValueTypes&... values)
{ {
bind(index, value); bind(index, value);
bindValuesByIndex(index + 1, values...); bindValuesByIndex(index + 1, values...);
} }
template<typename ValueType> template<typename ValueType>
void bindValuesByName(Utils::SmallStringView name, ValueType value) void bindValuesByName(Utils::SmallStringView name, const ValueType &value)
{ {
bind(bindingIndexForName(name), value); bind(bindingIndexForName(name), value);
} }
template<typename ValueType, typename... ValueTypes> template<typename ValueType, typename... ValueTypes>
void bindValuesByName(Utils::SmallStringView name, ValueType value, ValueTypes... values) void bindValuesByName(Utils::SmallStringView name, const ValueType &value, const ValueTypes&... values)
{ {
bind(bindingIndexForName(name), value); bind(bindingIndexForName(name), value);
bindValuesByName(values...); bindValuesByName(values...);
@@ -469,10 +391,10 @@ extern template SQLITE_EXPORT long long Statement::toValue<long long>(Utils::Sma
extern template SQLITE_EXPORT double Statement::toValue<double>(Utils::SmallStringView sqlStatement, Database &database); extern template SQLITE_EXPORT double Statement::toValue<double>(Utils::SmallStringView sqlStatement, Database &database);
extern template SQLITE_EXPORT Utils::SmallString Statement::toValue<Utils::SmallString>(Utils::SmallStringView sqlStatement, Database &database); extern template SQLITE_EXPORT Utils::SmallString Statement::toValue<Utils::SmallString>(Utils::SmallStringView sqlStatement, Database &database);
template <> SQLITE_EXPORT int Statement::value<int>(int column) const; template <> SQLITE_EXPORT int Statement::fetchValue<int>(int column) const;
template <> SQLITE_EXPORT long Statement::value<long>(int column) const; template <> SQLITE_EXPORT long Statement::fetchValue<long>(int column) const;
template <> SQLITE_EXPORT long long Statement::value<long long>(int column) const; template <> SQLITE_EXPORT long long Statement::fetchValue<long long>(int column) const;
template <> SQLITE_EXPORT double Statement::value<double>(int column) const; template <> SQLITE_EXPORT double Statement::fetchValue<double>(int column) const;
extern template SQLITE_EXPORT Utils::SmallString Statement::value<Utils::SmallString>(int column) const; extern template SQLITE_EXPORT Utils::SmallString Statement::fetchValue<Utils::SmallString>(int column) const;
extern template SQLITE_EXPORT Utils::PathString Statement::value<Utils::PathString>(int column) const; extern template SQLITE_EXPORT Utils::PathString Statement::fetchValue<Utils::PathString>(int column) const;
} // namespace Sqlite } // namespace Sqlite

View File

@@ -27,6 +27,8 @@
#include "sqliteglobal.h" #include "sqliteglobal.h"
#include <mutex>
namespace Sqlite { namespace Sqlite {
class DatabaseBackend; class DatabaseBackend;
@@ -50,11 +52,13 @@ public:
protected: protected:
AbstractTransaction(Database &database) AbstractTransaction(Database &database)
: m_database(database) : m_databaseLock(database.databaseMutex()),
m_database(database)
{ {
} }
private: private:
std::lock_guard<typename Database::MutexType> m_databaseLock;
Database &m_database; Database &m_database;
bool m_isAlreadyCommited = false; bool m_isAlreadyCommited = false;
}; };

View File

@@ -37,7 +37,7 @@ WriteStatement::WriteStatement(Utils::SmallStringView sqlStatement,
void WriteStatement::checkIsWritableStatement() void WriteStatement::checkIsWritableStatement()
{ {
if (isReadOnlyStatement()) if (isReadOnlyStatement())
throwException("SqliteStatement::SqliteWriteStatement: is not a writable statement!"); throw NotWriteSqlStatement("SqliteStatement::SqliteWriteStatement: is not a writable statement!");
} }
} // namespace Sqlite } // namespace Sqlite

View File

@@ -35,13 +35,6 @@ public:
explicit WriteStatement(Utils::SmallStringView sqlStatement, Database &database); explicit WriteStatement(Utils::SmallStringView sqlStatement, Database &database);
using Statement::execute; using Statement::execute;
using Statement::reset;
using Statement::bind;
using Statement::bindValues;
using Statement::bindNameValues;
using Statement::bindingIndexForName;
using Statement::setBindingColumnNames;
using Statement::bindingColumnNames;
using Statement::database; using Statement::database;
using Statement::write; using Statement::write;
using Statement::writeNamed; using Statement::writeNamed;

View File

@@ -72,6 +72,7 @@ QRegularExpression CamelHumpMatcher::createCamelHumpRegExp(
const QLatin1String lowercaseWordFirst("(?<=\\b|[A-Z0-9_])"); const QLatin1String lowercaseWordFirst("(?<=\\b|[A-Z0-9_])");
const QLatin1String uppercaseWordContinuation("[a-z0-9_]*"); const QLatin1String uppercaseWordContinuation("[a-z0-9_]*");
const QLatin1String lowercaseWordContinuation("(?:[a-zA-Z0-9]*_)?"); const QLatin1String lowercaseWordContinuation("(?:[a-zA-Z0-9]*_)?");
const QLatin1String upperSnakeWordContinuation("[A-Z0-9]*_");
for (const QChar &c : pattern) { for (const QChar &c : pattern) {
if (!c.isLetter()) { if (!c.isLetter()) {
if (c == question) if (c == question)
@@ -90,7 +91,9 @@ QRegularExpression CamelHumpMatcher::createCamelHumpRegExp(
keyRegExp += '|' + lowercaseWordFirst + QRegularExpression::escape(c.toLower()) + ')'; keyRegExp += '|' + lowercaseWordFirst + QRegularExpression::escape(c.toLower()) + ')';
} else { } else {
keyRegExp += ")|" + lowercaseWordContinuation; keyRegExp += ")|" + lowercaseWordContinuation;
keyRegExp += '(' + QRegularExpression::escape(c.toLower()) + ')'; keyRegExp += '(' + QRegularExpression::escape(c.toLower()) + ")|";
keyRegExp += upperSnakeWordContinuation;
keyRegExp += '(' + QRegularExpression::escape(c.toUpper()) + ')';
} }
keyRegExp += ')'; keyRegExp += ')';
} else { } else {

View File

@@ -41,6 +41,8 @@ namespace Utils {
using std::experimental::optional; using std::experimental::optional;
// --> Utils::nullopt // --> Utils::nullopt
using std::experimental::nullopt; using std::experimental::nullopt;
// --> Utils::in_place
using std::experimental::in_place;
// TODO: make_optional is a copy, since there is no sensible way to import functions in C++ // TODO: make_optional is a copy, since there is no sensible way to import functions in C++
template <class T> template <class T>

View File

@@ -322,22 +322,22 @@ public:
reverse_iterator rbegin() noexcept reverse_iterator rbegin() noexcept
{ {
return reverse_iterator(end() - static_cast<std::size_t>(1)); return reverse_iterator(end());
} }
reverse_iterator rend() noexcept reverse_iterator rend() noexcept
{ {
return reverse_iterator(begin() - static_cast<std::size_t>(1)); return reverse_iterator(begin());
} }
const_reverse_iterator rbegin() const noexcept const_reverse_iterator rbegin() const noexcept
{ {
return const_reverse_iterator(end() - static_cast<std::size_t>(1)); return const_reverse_iterator(end());
} }
const_reverse_iterator rend() const noexcept const_reverse_iterator rend() const noexcept
{ {
return const_reverse_iterator(begin() - static_cast<std::size_t>(1)); return const_reverse_iterator(begin());
} }
const_iterator begin() const noexcept const_iterator begin() const noexcept

View File

@@ -80,12 +80,12 @@ public:
const_reverse_iterator rbegin() const noexcept const_reverse_iterator rbegin() const noexcept
{ {
return const_reverse_iterator(end() - static_cast<std::size_t>(1)); return const_reverse_iterator(end());
} }
const_reverse_iterator rend() const noexcept const_reverse_iterator rend() const noexcept
{ {
return const_reverse_iterator(begin() - static_cast<std::size_t>(1)); return const_reverse_iterator(begin());
} }
constexpr static constexpr static

View File

@@ -97,6 +97,12 @@ public:
return m_size == 0; return m_size == 0;
} }
constexpr
size_type empty() const noexcept
{
return m_size == 0;
}
constexpr constexpr
const_iterator begin() const noexcept const_iterator begin() const noexcept
{ {
@@ -111,12 +117,12 @@ public:
const_reverse_iterator rbegin() const noexcept const_reverse_iterator rbegin() const noexcept
{ {
return const_reverse_iterator(end() - static_cast<std::size_t>(1)); return const_reverse_iterator(end());
} }
const_reverse_iterator rend() const noexcept const_reverse_iterator rend() const noexcept
{ {
return const_reverse_iterator(begin() - static_cast<std::size_t>(1)); return const_reverse_iterator(begin());
} }
operator std::string() const operator std::string() const

View File

@@ -34,6 +34,7 @@
#include <QFileInfo> #include <QFileInfo>
#include <QCommonStyle> #include <QCommonStyle>
#include <QStyleOption> #include <QStyleOption>
#include <QWindow>
#include <qmath.h> #include <qmath.h>
// Clamps float color values within (0, 255) // Clamps float color values within (0, 255)
@@ -397,7 +398,9 @@ void StyleHelper::drawIconWithShadow(const QIcon &icon, const QRect &rect,
QPainter *p, QIcon::Mode iconMode, int dipRadius, const QColor &color, const QPoint &dipOffset) QPainter *p, QIcon::Mode iconMode, int dipRadius, const QColor &color, const QPoint &dipOffset)
{ {
QPixmap cache; QPixmap cache;
QString pixmapName = QString::fromLatin1("icon %0 %1 %2").arg(icon.cacheKey()).arg(iconMode).arg(rect.height()); const int devicePixelRatio = p->device()->devicePixelRatio();
QString pixmapName = QString::fromLatin1("icon %0 %1 %2 %3")
.arg(icon.cacheKey()).arg(iconMode).arg(rect.height()).arg(devicePixelRatio);
if (!QPixmapCache::find(pixmapName, cache)) { if (!QPixmapCache::find(pixmapName, cache)) {
// High-dpi support: The in parameters (rect, radius, offset) are in // High-dpi support: The in parameters (rect, radius, offset) are in
@@ -405,9 +408,8 @@ void StyleHelper::drawIconWithShadow(const QIcon &icon, const QRect &rect,
// return a high-dpi pixmap, which will in that case have a devicePixelRatio // return a high-dpi pixmap, which will in that case have a devicePixelRatio
// different than 1. The shadow drawing caluculations are done in device // different than 1. The shadow drawing caluculations are done in device
// pixels. // pixels.
QWindow *window = QApplication::allWidgets().first()->windowHandle(); QWindow *window = dynamic_cast<QWidget*>(p->device())->window()->windowHandle();
QPixmap px = icon.pixmap(window, rect.size(), iconMode); QPixmap px = icon.pixmap(window, rect.size(), iconMode);
int devicePixelRatio = qCeil(px.devicePixelRatio());
int radius = dipRadius * devicePixelRatio; int radius = dipRadius * devicePixelRatio;
QPoint offset = dipOffset * devicePixelRatio; QPoint offset = dipOffset * devicePixelRatio;
cache = QPixmap(px.size() + QSize(radius * 2, radius * 2)); cache = QPixmap(px.size() + QSize(radius * 2, radius * 2));
@@ -415,7 +417,8 @@ void StyleHelper::drawIconWithShadow(const QIcon &icon, const QRect &rect,
QPainter cachePainter(&cache); QPainter cachePainter(&cache);
if (iconMode == QIcon::Disabled) { if (iconMode == QIcon::Disabled) {
const bool hasDisabledState = icon.availableSizes(QIcon::Disabled).contains(px.size()); const bool hasDisabledState =
icon.availableSizes().count() == icon.availableSizes(QIcon::Disabled).count();
if (!hasDisabledState) if (!hasDisabledState)
px = disabledSideBarIcon(icon.pixmap(window, rect.size())); px = disabledSideBarIcon(icon.pixmap(window, rect.size()));
} else if (creatorTheme()->flag(Theme::ToolBarIconShadow)) { } else if (creatorTheme()->flag(Theme::ToolBarIconShadow)) {

View File

@@ -23,14 +23,14 @@
** **
****************************************************************************/ ****************************************************************************/
#include "convenience.h" #include "textutils.h"
#include <QTextDocument> #include <QTextDocument>
#include <QTextBlock> #include <QTextBlock>
#include <QTextCursor> #include <QTextCursor>
namespace TextEditor { namespace Utils {
namespace Convenience { namespace Text {
bool convertPosition(const QTextDocument *document, int pos, int *line, int *column) bool convertPosition(const QTextDocument *document, int pos, int *line, int *column)
{ {
@@ -121,5 +121,5 @@ QTextCursor wordStartCursor(const QTextCursor &textCursor)
return cursor; return cursor;
} }
} // Util } // Text
} // TextEditor } // Utils

View File

@@ -25,30 +25,28 @@
#pragma once #pragma once
#include "texteditor_global.h" #include "utils_global.h"
#include <QString> #include <QString>
QT_BEGIN_NAMESPACE QT_FORWARD_DECLARE_CLASS(QTextDocument)
class QTextDocument; QT_FORWARD_DECLARE_CLASS(QTextCursor)
class QTextCursor;
QT_END_NAMESPACE
namespace TextEditor { namespace Utils {
namespace Convenience { namespace Text {
// line is 1-based, column is 0-based // line is 1-based, column is 0-based
TEXTEDITOR_EXPORT bool convertPosition(const QTextDocument *document, QTCREATOR_UTILS_EXPORT bool convertPosition(const QTextDocument *document,
int pos, int pos,
int *line, int *column); int *line, int *column);
TEXTEDITOR_EXPORT QString textAt(QTextCursor tc, int pos, int length); QTCREATOR_UTILS_EXPORT QString textAt(QTextCursor tc, int pos, int length);
TEXTEDITOR_EXPORT QTextCursor selectAt(QTextCursor textCursor, uint line, uint column, uint length); QTCREATOR_UTILS_EXPORT QTextCursor selectAt(QTextCursor textCursor, uint line, uint column, uint length);
TEXTEDITOR_EXPORT QTextCursor flippedCursor(const QTextCursor &cursor); QTCREATOR_UTILS_EXPORT QTextCursor flippedCursor(const QTextCursor &cursor);
TEXTEDITOR_EXPORT QTextCursor wordStartCursor(const QTextCursor &cursor); QTCREATOR_UTILS_EXPORT QTextCursor wordStartCursor(const QTextCursor &cursor);
} // Util } // Text
} // TextEditor } // Utils

View File

@@ -115,7 +115,8 @@ SOURCES += $$PWD/environment.cpp \
$$PWD/utilsicons.cpp \ $$PWD/utilsicons.cpp \
$$PWD/guard.cpp \ $$PWD/guard.cpp \
$$PWD/highlightingitemdelegate.cpp \ $$PWD/highlightingitemdelegate.cpp \
$$PWD/camelhumpmatcher.cpp $$PWD/camelhumpmatcher.cpp \
$$PWD/textutils.cpp
win32:SOURCES += $$PWD/consoleprocess_win.cpp win32:SOURCES += $$PWD/consoleprocess_win.cpp
else:SOURCES += $$PWD/consoleprocess_unix.cpp else:SOURCES += $$PWD/consoleprocess_unix.cpp
@@ -244,7 +245,8 @@ HEADERS += \
$$PWD/../3rdparty/optional/optional.hpp \ $$PWD/../3rdparty/optional/optional.hpp \
$$PWD/qtcfallthrough.h \ $$PWD/qtcfallthrough.h \
$$PWD/highlightingitemdelegate.h \ $$PWD/highlightingitemdelegate.h \
$$PWD/camelhumpmatcher.h $$PWD/camelhumpmatcher.h \
$$PWD/textutils.h
FORMS += $$PWD/filewizardpage.ui \ FORMS += $$PWD/filewizardpage.ui \
$$PWD/projectintropage.ui \ $$PWD/projectintropage.ui \

View File

@@ -232,6 +232,8 @@ Project {
"textfieldcombobox.h", "textfieldcombobox.h",
"textfileformat.cpp", "textfileformat.cpp",
"textfileformat.h", "textfileformat.h",
"textutils.cpp",
"textutils.h",
"treemodel.cpp", "treemodel.cpp",
"treemodel.h", "treemodel.h",
"treeviewcombobox.cpp", "treeviewcombobox.cpp",

View File

@@ -293,6 +293,7 @@ AndroidRunnerWorker::AndroidRunnerWorker(RunControl *runControl, const AndroidRu
QTC_ASSERT(server.listen(QHostAddress::LocalHost) QTC_ASSERT(server.listen(QHostAddress::LocalHost)
|| server.listen(QHostAddress::LocalHostIPv6), || server.listen(QHostAddress::LocalHostIPv6),
qDebug() << tr("No free ports available on host for QML debugging.")); qDebug() << tr("No free ports available on host for QML debugging."));
m_qmlServer.setScheme(urlTcpScheme());
m_qmlServer.setHost(server.serverAddress().toString()); m_qmlServer.setHost(server.serverAddress().toString());
m_qmlServer.setPort(server.serverPort()); m_qmlServer.setPort(server.serverPort());
} }

View File

@@ -213,7 +213,7 @@ QString AndroidToolChain::makeCommand(const Environment &env) const
if (HostOsInfo::isWindowsHost()) { if (HostOsInfo::isWindowsHost()) {
FileName tmp = env.searchInPath(QLatin1String("ma-make.exe"), extraDirectories); FileName tmp = env.searchInPath(QLatin1String("ma-make.exe"), extraDirectories);
if (!tmp.isEmpty()) if (!tmp.isEmpty())
return QString(); return tmp.toString();
tmp = env.searchInPath(QLatin1String("mingw32-make"), extraDirectories); tmp = env.searchInPath(QLatin1String("mingw32-make"), extraDirectories);
return tmp.isEmpty() ? QLatin1String("mingw32-make") : tmp.toString(); return tmp.isEmpty() ? QLatin1String("mingw32-make") : tmp.toString();
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 B

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 255 B

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 B

After

Width:  |  Height:  |  Size: 185 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 277 B

After

Width:  |  Height:  |  Size: 280 B

View File

@@ -45,12 +45,12 @@
#include <diffeditor/differ.h> #include <diffeditor/differ.h>
#include <projectexplorer/project.h> #include <projectexplorer/project.h>
#include <projectexplorer/projecttree.h> #include <projectexplorer/projecttree.h>
#include <texteditor/convenience.h>
#include <texteditor/textdocument.h> #include <texteditor/textdocument.h>
#include <texteditor/textdocumentlayout.h> #include <texteditor/textdocumentlayout.h>
#include <texteditor/texteditor.h> #include <texteditor/texteditor.h>
#include <texteditor/texteditorconstants.h> #include <texteditor/texteditorconstants.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/textutils.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/mimetypes/mimedatabase.h> #include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -169,7 +169,7 @@ QString sourceData(TextEditorWidget *editor, int startPos, int endPos)
{ {
return (startPos < 0) return (startPos < 0)
? editor->toPlainText() ? editor->toPlainText()
: Convenience::textAt(editor->textCursor(), startPos, (endPos - startPos)); : Utils::Text::textAt(editor->textCursor(), startPos, (endPos - startPos));
} }
bool isAutoFormatApplicable(const Core::IDocument *document, bool isAutoFormatApplicable(const Core::IDocument *document,
@@ -496,6 +496,18 @@ QString BeautifierPlugin::msgFormatSelectedText()
return tr("Format &Selected Text"); return tr("Format &Selected Text");
} }
QString BeautifierPlugin::msgFormatAtCursor()
{
//: Menu entry
return tr("&Format at Cursor");
}
QString BeautifierPlugin::msgDisableFormattingSelectedText()
{
//: Menu entry
return tr("&Disable Formatting for Selected Text");
}
QString BeautifierPlugin::msgCommandPromptDialogTitle(const QString &command) QString BeautifierPlugin::msgCommandPromptDialogTitle(const QString &command)
{ {
//: File dialog title for path chooser when choosing binary //: File dialog title for path chooser when choosing binary

View File

@@ -80,6 +80,8 @@ public:
static QString msgCannotGetConfigurationFile(const QString &command); static QString msgCannotGetConfigurationFile(const QString &command);
static QString msgFormatCurrentFile(); static QString msgFormatCurrentFile();
static QString msgFormatSelectedText(); static QString msgFormatSelectedText();
static QString msgFormatAtCursor();
static QString msgDisableFormattingSelectedText();
static QString msgCommandPromptDialogTitle(const QString &command); static QString msgCommandPromptDialogTitle(const QString &command);
static void showError(const QString &error); static void showError(const QString &error);

View File

@@ -48,6 +48,7 @@
#include <QAction> #include <QAction>
#include <QMenu> #include <QMenu>
#include <QTextBlock>
namespace Beautifier { namespace Beautifier {
namespace Internal { namespace Internal {
@@ -82,11 +83,19 @@ bool ClangFormat::initialize()
menu->addAction(cmd); menu->addAction(cmd);
connect(m_formatFile, &QAction::triggered, this, &ClangFormat::formatFile); connect(m_formatFile, &QAction::triggered, this, &ClangFormat::formatFile);
m_formatRange = new QAction(BeautifierPlugin::msgFormatSelectedText(), this); m_formatRange = new QAction(BeautifierPlugin::msgFormatAtCursor(), this);
cmd = Core::ActionManager::registerAction(m_formatRange, cmd = Core::ActionManager::registerAction(m_formatRange,
Constants::ClangFormat::ACTION_FORMATSELECTED); Constants::ClangFormat::ACTION_FORMATATCURSOR);
menu->addAction(cmd); menu->addAction(cmd);
connect(m_formatRange, &QAction::triggered, this, &ClangFormat::formatSelectedText); connect(m_formatRange, &QAction::triggered, this, &ClangFormat::formatAtCursor);
m_disableFormattingSelectedText
= new QAction(BeautifierPlugin::msgDisableFormattingSelectedText(), this);
cmd = Core::ActionManager::registerAction(
m_disableFormattingSelectedText, Constants::ClangFormat::ACTION_DISABLEFORMATTINGSELECTED);
menu->addAction(cmd);
connect(m_disableFormattingSelectedText, &QAction::triggered,
this, &ClangFormat::disableFormattingSelectedText);
Core::ActionManager::actionContainer(Constants::MENU_ID)->addMenu(menu); Core::ActionManager::actionContainer(Constants::MENU_ID)->addMenu(menu);
@@ -113,7 +122,7 @@ void ClangFormat::formatFile()
m_beautifierPlugin->formatCurrentFile(command()); m_beautifierPlugin->formatCurrentFile(command());
} }
void ClangFormat::formatSelectedText() void ClangFormat::formatAtCursor()
{ {
const TextEditor::TextEditorWidget *widget const TextEditor::TextEditorWidget *widget
= TextEditor::TextEditorWidget::currentTextEditorWidget(); = TextEditor::TextEditorWidget::currentTextEditorWidget();
@@ -125,11 +134,53 @@ void ClangFormat::formatSelectedText()
const int offset = tc.selectionStart(); const int offset = tc.selectionStart();
const int length = tc.selectionEnd() - offset; const int length = tc.selectionEnd() - offset;
m_beautifierPlugin->formatCurrentFile(command(offset, length)); m_beautifierPlugin->formatCurrentFile(command(offset, length));
} else if (m_settings->formatEntireFileFallback()) { } else {
formatFile(); // Pretend that the current line was selected.
// Note that clang-format will extend the range to the next bigger
// syntactic construct if needed.
const QTextBlock block = tc.block();
const int offset = block.position();
const int length = block.length();
m_beautifierPlugin->formatCurrentFile(command(offset, length));
} }
} }
void ClangFormat::disableFormattingSelectedText()
{
TextEditor::TextEditorWidget *widget = TextEditor::TextEditorWidget::currentTextEditorWidget();
if (!widget)
return;
const QTextCursor tc = widget->textCursor();
if (!tc.hasSelection())
return;
// Insert start marker
const QTextBlock selectionStartBlock = tc.document()->findBlock(tc.selectionStart());
QTextCursor insertCursor(tc.document());
insertCursor.beginEditBlock();
insertCursor.setPosition(selectionStartBlock.position());
insertCursor.insertText("// clang-format off\n");
const int positionToRestore = tc.position();
// Insert end marker
QTextBlock selectionEndBlock = tc.document()->findBlock(tc.selectionEnd());
insertCursor.setPosition(selectionEndBlock.position() + selectionEndBlock.length() - 1);
insertCursor.insertText("\n// clang-format on");
insertCursor.endEditBlock();
// Reset the cursor position in order to clear the selection.
QTextCursor restoreCursor(tc.document());
restoreCursor.setPosition(positionToRestore);
widget->setTextCursor(restoreCursor);
// The indentation of these markers might be undesired, so reformat.
// This is not optimal because two undo steps will be needed to remove the markers.
const int reformatTextLength = insertCursor.position() - selectionStartBlock.position();
m_beautifierPlugin->formatCurrentFile(command(selectionStartBlock.position(),
reformatTextLength));
}
Command ClangFormat::command() const Command ClangFormat::command() const
{ {
Command command; Command command;

View File

@@ -54,10 +54,12 @@ public:
private: private:
void formatFile(); void formatFile();
void formatSelectedText(); void formatAtCursor();
void disableFormattingSelectedText();
BeautifierPlugin *m_beautifierPlugin; BeautifierPlugin *m_beautifierPlugin;
QAction *m_formatFile = nullptr; QAction *m_formatFile = nullptr;
QAction *m_formatRange = nullptr; QAction *m_formatRange = nullptr;
QAction *m_disableFormattingSelectedText = nullptr;
ClangFormatSettings *m_settings; ClangFormatSettings *m_settings;
Command command(int offset, int length) const; Command command(int offset, int length) const;
}; };

View File

@@ -33,7 +33,8 @@ namespace ClangFormat {
const char DISPLAY_NAME[] = QT_TRANSLATE_NOOP("Beautifier::Internal::ClangFormat::ClangFormat", "ClangFormat"); const char DISPLAY_NAME[] = QT_TRANSLATE_NOOP("Beautifier::Internal::ClangFormat::ClangFormat", "ClangFormat");
const char ACTION_FORMATFILE[] = "ClangFormat.FormatFile"; const char ACTION_FORMATFILE[] = "ClangFormat.FormatFile";
const char ACTION_FORMATSELECTED[] = "ClangFormat.FormatSelectedText"; const char ACTION_FORMATATCURSOR[] = "ClangFormat.FormatAtCursor";
const char ACTION_DISABLEFORMATTINGSELECTED[] = "ClangFormat.DisableFormattingSelectedText";
const char MENU_ID[] = "ClangFormat.Menu"; const char MENU_ID[] = "ClangFormat.Menu";
const char OPTION_ID[] = "ClangFormat"; const char OPTION_ID[] = "ClangFormat";
const char SETTINGS_NAME[] = "clangformat"; const char SETTINGS_NAME[] = "clangformat";

View File

@@ -78,7 +78,6 @@ void ClangFormatOptionsPageWidget::restore()
const int fallbackStyleIndex = ui->fallbackStyle->findText(m_settings->fallbackStyle()); const int fallbackStyleIndex = ui->fallbackStyle->findText(m_settings->fallbackStyle());
if (fallbackStyleIndex != -1) if (fallbackStyleIndex != -1)
ui->fallbackStyle->setCurrentIndex(fallbackStyleIndex); ui->fallbackStyle->setCurrentIndex(fallbackStyleIndex);
ui->formatEntireFileFallback->setChecked(m_settings->formatEntireFileFallback());
ui->configurations->setSettings(m_settings); ui->configurations->setSettings(m_settings);
ui->configurations->setCurrentConfiguration(m_settings->customStyle()); ui->configurations->setCurrentConfiguration(m_settings->customStyle());
@@ -96,7 +95,6 @@ void ClangFormatOptionsPageWidget::apply()
m_settings->setPredefinedStyle(ui->predefinedStyle->currentText()); m_settings->setPredefinedStyle(ui->predefinedStyle->currentText());
m_settings->setFallbackStyle(ui->fallbackStyle->currentText()); m_settings->setFallbackStyle(ui->fallbackStyle->currentText());
m_settings->setCustomStyle(ui->configurations->currentConfiguration()); m_settings->setCustomStyle(ui->configurations->currentConfiguration());
m_settings->setFormatEntireFileFallback(ui->formatEntireFileFallback->isChecked());
m_settings->save(); m_settings->save();
// update since not all MIME types are accepted (invalids or duplicates) // update since not all MIME types are accepted (invalids or duplicates)

View File

@@ -20,6 +20,19 @@
<string>Options</string> <string>Options</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<widget class="QRadioButton" name="useCustomizedStyle">
<property name="text">
<string>Use customized style:</string>
</property>
<property name="autoExclusive">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="Beautifier::Internal::ConfigurationPanel" name="configurations" native="true"/>
</item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QRadioButton" name="usePredefinedStyle"> <widget class="QRadioButton" name="usePredefinedStyle">
<property name="sizePolicy"> <property name="sizePolicy">
@@ -62,29 +75,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="QRadioButton" name="useCustomizedStyle">
<property name="text">
<string>Use customized style:</string>
</property>
<property name="autoExclusive">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="Beautifier::Internal::ConfigurationPanel" name="configurations" native="true"/>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="formatEntireFileFallback">
<property name="toolTip">
<string>For action Format Selected Text.</string>
</property>
<property name="text">
<string>Format entire file if no text was selected</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View File

@@ -43,7 +43,6 @@ const char USE_PREDEFINED_STYLE[] = "usePredefinedStyle";
const char PREDEFINED_STYLE[] = "predefinedStyle"; const char PREDEFINED_STYLE[] = "predefinedStyle";
const char FALLBACK_STYLE[] = "fallbackStyle"; const char FALLBACK_STYLE[] = "fallbackStyle";
const char CUSTOM_STYLE[] = "customStyle"; const char CUSTOM_STYLE[] = "customStyle";
const char FORMAT_ENTIRE_FILE_FALLBACK[] = "formatEntireFileFallback";
} }
ClangFormatSettings::ClangFormatSettings() : ClangFormatSettings::ClangFormatSettings() :
@@ -54,7 +53,6 @@ ClangFormatSettings::ClangFormatSettings() :
m_settings.insert(PREDEFINED_STYLE, "LLVM"); m_settings.insert(PREDEFINED_STYLE, "LLVM");
m_settings.insert(FALLBACK_STYLE, "Default"); m_settings.insert(FALLBACK_STYLE, "Default");
m_settings.insert(CUSTOM_STYLE, QVariant()); m_settings.insert(CUSTOM_STYLE, QVariant());
m_settings.insert(FORMAT_ENTIRE_FILE_FALLBACK, QVariant(true));
read(); read();
} }
@@ -215,16 +213,6 @@ void ClangFormatSettings::setCustomStyle(const QString &customStyle)
m_settings.insert(CUSTOM_STYLE, QVariant(customStyle)); m_settings.insert(CUSTOM_STYLE, QVariant(customStyle));
} }
bool ClangFormatSettings::formatEntireFileFallback() const
{
return m_settings.value(FORMAT_ENTIRE_FILE_FALLBACK).toBool();
}
void ClangFormatSettings::setFormatEntireFileFallback(bool formatEntireFileFallback)
{
m_settings.insert(FORMAT_ENTIRE_FILE_FALLBACK, QVariant(formatEntireFileFallback));
}
QStringList ClangFormatSettings::predefinedStyles() const QStringList ClangFormatSettings::predefinedStyles() const
{ {
return {"LLVM", "Google", "Chromium", "Mozilla", "WebKit", "File"}; return {"LLVM", "Google", "Chromium", "Mozilla", "WebKit", "File"};

View File

@@ -54,9 +54,6 @@ public:
QString customStyle() const; QString customStyle() const;
void setCustomStyle(const QString &customStyle); void setCustomStyle(const QString &customStyle);
bool formatEntireFileFallback() const;
void setFormatEntireFileFallback(bool formatEntireFileFallback);
QStringList predefinedStyles() const; QStringList predefinedStyles() const;
QStringList fallbackStyles() const; QStringList fallbackStyles() const;

View File

@@ -275,7 +275,6 @@ CppTools::SymbolInfo toSymbolInfo(const FollowSymbolMessage &message)
result.endLine = static_cast<int>(end.line()); result.endLine = static_cast<int>(end.line());
result.endColumn = static_cast<int>(end.column()); result.endColumn = static_cast<int>(end.column());
result.fileName = start.filePath(); result.fileName = start.filePath();
result.failedToFollow = message.failedToFollow();
return result; return result;
} }
@@ -748,14 +747,12 @@ QFuture<CppTools::SymbolInfo> IpcCommunicator::requestFollowSymbol(
const FileContainer &curFileContainer, const FileContainer &curFileContainer,
const QVector<Utf8String> &dependentFiles, const QVector<Utf8String> &dependentFiles,
quint32 line, quint32 line,
quint32 column, quint32 column)
bool resolveTarget)
{ {
const RequestFollowSymbolMessage message(curFileContainer, const RequestFollowSymbolMessage message(curFileContainer,
dependentFiles, dependentFiles,
line, line,
column, column);
resolveTarget);
m_ipcSender->requestFollowSymbol(message); m_ipcSender->requestFollowSymbol(message);
return m_ipcReceiver.addExpectedRequestFollowSymbolMessage(message.ticketNumber()); return m_ipcReceiver.addExpectedRequestFollowSymbolMessage(message.ticketNumber());

View File

@@ -169,8 +169,7 @@ public:
QFuture<CppTools::SymbolInfo> requestFollowSymbol(const FileContainer &curFileContainer, QFuture<CppTools::SymbolInfo> requestFollowSymbol(const FileContainer &curFileContainer,
const QVector<Utf8String> &dependentFiles, const QVector<Utf8String> &dependentFiles,
quint32 line, quint32 line,
quint32 column, quint32 column);
bool resolveTarget);
void completeCode(ClangCompletionAssistProcessor *assistProcessor, const QString &filePath, void completeCode(ClangCompletionAssistProcessor *assistProcessor, const QString &filePath,
quint32 line, quint32 line,
quint32 column, quint32 column,

View File

@@ -42,7 +42,6 @@
#include <texteditor/codeassist/assistproposalitem.h> #include <texteditor/codeassist/assistproposalitem.h>
#include <texteditor/codeassist/functionhintproposal.h> #include <texteditor/codeassist/functionhintproposal.h>
#include <texteditor/codeassist/ifunctionhintproposalmodel.h> #include <texteditor/codeassist/ifunctionhintproposalmodel.h>
#include <texteditor/convenience.h>
#include <cplusplus/BackwardsScanner.h> #include <cplusplus/BackwardsScanner.h>
#include <cplusplus/ExpressionUnderCursor.h> #include <cplusplus/ExpressionUnderCursor.h>
@@ -52,6 +51,7 @@
#include <clangsupport/filecontainer.h> #include <clangsupport/filecontainer.h>
#include <utils/algorithm.h> #include <utils/algorithm.h>
#include <utils/textutils.h>
#include <utils/mimetypes/mimedatabase.h> #include <utils/mimetypes/mimedatabase.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -556,10 +556,7 @@ ClangCompletionAssistProcessor::extractLineColumn(int position)
return {-1, -1}; return {-1, -1};
int line = -1, column = -1; int line = -1, column = -1;
TextEditor::Convenience::convertPosition(m_interface->textDocument(), ::Utils::Text::convertPosition(m_interface->textDocument(), position, &line, &column);
position,
&line,
&column);
const QTextBlock block = m_interface->textDocument()->findBlock(position); const QTextBlock block = m_interface->textDocument()->findBlock(position);
column += ClangCodeModel::Utils::extraUtf8CharsShift(block.text(), column) + 1; column += ClangCodeModel::Utils::extraUtf8CharsShift(block.text(), column) + 1;
return {line, column}; return {line, column};

View File

@@ -33,11 +33,11 @@
#include <cpptools/cpptoolsconstants.h> #include <cpptools/cpptoolsconstants.h>
#include <texteditor/convenience.h>
#include <texteditor/fontsettings.h> #include <texteditor/fontsettings.h>
#include <texteditor/textdocument.h> #include <texteditor/textdocument.h>
#include <texteditor/texteditorsettings.h> #include <texteditor/texteditorsettings.h>
#include <utils/textutils.h>
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/proxyaction.h> #include <utils/proxyaction.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -176,7 +176,7 @@ void addErrorSelections(const QVector<ClangBackEnd::DiagnosticContainer> &diagno
ClangBackEnd::SourceLocationContainer toSourceLocation(QTextDocument *textDocument, int position) ClangBackEnd::SourceLocationContainer toSourceLocation(QTextDocument *textDocument, int position)
{ {
int line, column; int line, column;
if (TextEditor::Convenience::convertPosition(textDocument, position, &line, &column)) if (Utils::Text::convertPosition(textDocument, position, &line, &column))
return ClangBackEnd::SourceLocationContainer(Utf8String(), line, column); return ClangBackEnd::SourceLocationContainer(Utf8String(), line, column);
return ClangBackEnd::SourceLocationContainer(); return ClangBackEnd::SourceLocationContainer();

View File

@@ -47,7 +47,6 @@
#include <cpptools/cppworkingcopy.h> #include <cpptools/cppworkingcopy.h>
#include <cpptools/editordocumenthandle.h> #include <cpptools/editordocumenthandle.h>
#include <texteditor/convenience.h>
#include <texteditor/displaysettings.h> #include <texteditor/displaysettings.h>
#include <texteditor/fontsettings.h> #include <texteditor/fontsettings.h>
#include <texteditor/texteditor.h> #include <texteditor/texteditor.h>
@@ -56,6 +55,7 @@
#include <cplusplus/CppDocument.h> #include <cplusplus/CppDocument.h>
#include <utils/textutils.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/runextensions.h> #include <utils/runextensions.h>
@@ -225,6 +225,12 @@ toTextEditorBlocks(QTextDocument *textDocument,
} }
} }
const QVector<ClangBackEnd::HighlightingMarkContainer>
&ClangEditorDocumentProcessor::highlightingMarks() const
{
return m_highlightingMarks;
}
void ClangEditorDocumentProcessor::updateHighlighting( void ClangEditorDocumentProcessor::updateHighlighting(
const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks, const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks,
const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges, const QVector<ClangBackEnd::SourceRangeContainer> &skippedPreprocessorRanges,
@@ -234,6 +240,7 @@ void ClangEditorDocumentProcessor::updateHighlighting(
const auto skippedPreprocessorBlocks = toTextEditorBlocks(textDocument(), skippedPreprocessorRanges); const auto skippedPreprocessorBlocks = toTextEditorBlocks(textDocument(), skippedPreprocessorRanges);
emit ifdefedOutBlocksUpdated(documentRevision, skippedPreprocessorBlocks); emit ifdefedOutBlocksUpdated(documentRevision, skippedPreprocessorBlocks);
m_highlightingMarks = highlightingMarks;
m_semanticHighlighter.setHighlightingRunner( m_semanticHighlighter.setHighlightingRunner(
[highlightingMarks]() { [highlightingMarks]() {
auto *reporter = new HighlightingMarksReporter(highlightingMarks); auto *reporter = new HighlightingMarksReporter(highlightingMarks);
@@ -246,10 +253,8 @@ void ClangEditorDocumentProcessor::updateHighlighting(
static int currentLine(const TextEditor::AssistInterface &assistInterface) static int currentLine(const TextEditor::AssistInterface &assistInterface)
{ {
int line, column; int line, column;
TextEditor::Convenience::convertPosition(assistInterface.textDocument(), ::Utils::Text::convertPosition(assistInterface.textDocument(), assistInterface.position(),
assistInterface.position(), &line, &column);
&line,
&column);
return line; return line;
} }
@@ -315,10 +320,10 @@ static QFuture<CppTools::CursorInfo> defaultCursorInfoFuture()
static bool convertPosition(const QTextCursor &textCursor, int *line, int *column) static bool convertPosition(const QTextCursor &textCursor, int *line, int *column)
{ {
const bool converted = TextEditor::Convenience::convertPosition(textCursor.document(), const bool converted = ::Utils::Text::convertPosition(textCursor.document(),
textCursor.position(), textCursor.position(),
line, line,
column); column);
QTC_CHECK(converted); QTC_CHECK(converted);
return converted; return converted;
} }
@@ -376,7 +381,7 @@ static QVector<Utf8String> prioritizeByBaseName(const QString &curPath,
} }
QFuture<CppTools::SymbolInfo> QFuture<CppTools::SymbolInfo>
ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column, bool resolveTarget) ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column)
{ {
QVector<Utf8String> dependentFiles; QVector<Utf8String> dependentFiles;
CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance(); CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
@@ -390,8 +395,7 @@ ClangEditorDocumentProcessor::requestFollowSymbol(int line, int column, bool res
return m_ipcCommunicator.requestFollowSymbol(simpleFileContainer(), return m_ipcCommunicator.requestFollowSymbol(simpleFileContainer(),
dependentFiles, dependentFiles,
static_cast<quint32>(line), static_cast<quint32>(line),
static_cast<quint32>(column), static_cast<quint32>(column));
resolveTarget);
} }
ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithArguments() const ClangBackEnd::FileContainer ClangEditorDocumentProcessor::fileContainerWithArguments() const

View File

@@ -86,14 +86,14 @@ public:
void setParserConfig(const CppTools::BaseEditorDocumentParser::Configuration config) override; void setParserConfig(const CppTools::BaseEditorDocumentParser::Configuration config) override;
QFuture<CppTools::CursorInfo> cursorInfo(const CppTools::CursorInfoParams &params) override; QFuture<CppTools::CursorInfo> cursorInfo(const CppTools::CursorInfoParams &params) override;
QFuture<CppTools::SymbolInfo> requestFollowSymbol(int line, QFuture<CppTools::SymbolInfo> requestFollowSymbol(int line, int column) override;
int column,
bool resolveTarget) override;
ClangBackEnd::FileContainer fileContainerWithArguments() const; ClangBackEnd::FileContainer fileContainerWithArguments() const;
void clearDiagnosticsWithFixIts(); void clearDiagnosticsWithFixIts();
const QVector<ClangBackEnd::HighlightingMarkContainer> &highlightingMarks() const;
public: public:
static ClangEditorDocumentProcessor *get(const QString &filePath); static ClangEditorDocumentProcessor *get(const QString &filePath);
@@ -122,6 +122,7 @@ private:
QTimer m_updateTranslationUnitTimer; QTimer m_updateTranslationUnitTimer;
unsigned m_parserRevision; unsigned m_parserRevision;
QVector<ClangBackEnd::HighlightingMarkContainer> m_highlightingMarks;
CppTools::SemanticHighlighter m_semanticHighlighter; CppTools::SemanticHighlighter m_semanticHighlighter;
CppTools::BuiltinEditorDocumentProcessor m_builtinProcessor; CppTools::BuiltinEditorDocumentProcessor m_builtinProcessor;
}; };

View File

@@ -23,14 +23,78 @@
** **
****************************************************************************/ ****************************************************************************/
#include "clangfollowsymbol.h"
#include "clangeditordocumentprocessor.h" #include "clangeditordocumentprocessor.h"
#include "texteditor/texteditor.h" #include "clangfollowsymbol.h"
#include "texteditor/convenience.h"
#include <texteditor/texteditor.h>
#include <clangsupport/highlightingmarkcontainer.h>
#include <utils/textutils.h>
#include <utils/algorithm.h>
namespace ClangCodeModel { namespace ClangCodeModel {
namespace Internal { namespace Internal {
// Returns invalid Mark if it is not found at (line, column)
static bool findMark(const QVector<ClangBackEnd::HighlightingMarkContainer> &marks,
uint line,
uint column,
ClangBackEnd::HighlightingMarkContainer &mark)
{
mark = Utils::findOrDefault(marks,
[line, column](const ClangBackEnd::HighlightingMarkContainer &curMark) {
if (curMark.line() != line)
return false;
if (curMark.column() == column)
return true;
if (curMark.column() < column && curMark.column() + curMark.length() >= column)
return true;
return false;
});
if (mark.isInvalid())
return false;
return true;
}
static int getMarkPos(QTextCursor cursor, const ClangBackEnd::HighlightingMarkContainer &mark)
{
cursor.setPosition(0);
cursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, mark.line() - 1);
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::MoveAnchor, mark.column() - 1);
return cursor.position();
}
static TextEditor::TextEditorWidget::Link linkAtCursor(QTextCursor cursor,
const QString &filePath,
uint line,
uint column,
ClangEditorDocumentProcessor *processor)
{
using Link = TextEditor::TextEditorWidget::Link;
const QVector<ClangBackEnd::HighlightingMarkContainer> &marks
= processor->highlightingMarks();
ClangBackEnd::HighlightingMarkContainer mark;
if (!findMark(marks, line, column, mark))
return Link();
cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
const QString tokenStr = cursor.selectedText();
Link token(filePath, mark.line(), mark.column());
token.linkTextStart = getMarkPos(cursor, mark);
token.linkTextEnd = token.linkTextStart + mark.length();
if (mark.isIncludeDirectivePath()) {
if (tokenStr != "include" && tokenStr != "#" && tokenStr != "<")
return token;
return Link();
}
if (mark.isIdentifier() || tokenStr == "operator")
return token;
return Link();
}
TextEditor::TextEditorWidget::Link ClangFollowSymbol::findLink( TextEditor::TextEditorWidget::Link ClangFollowSymbol::findLink(
const CppTools::CursorInEditor &data, const CppTools::CursorInEditor &data,
bool resolveTarget, bool resolveTarget,
@@ -39,42 +103,39 @@ TextEditor::TextEditorWidget::Link ClangFollowSymbol::findLink(
CppTools::SymbolFinder *, CppTools::SymbolFinder *,
bool) bool)
{ {
Link link;
int lineNumber = 0, positionInBlock = 0; int lineNumber = 0, positionInBlock = 0;
QTextCursor cursor = TextEditor::Convenience::wordStartCursor(data.cursor()); QTextCursor cursor = Utils::Text::wordStartCursor(data.cursor());
TextEditor::Convenience::convertPosition(cursor.document(), cursor.position(), &lineNumber, Utils::Text::convertPosition(cursor.document(), cursor.position(), &lineNumber,
&positionInBlock); &positionInBlock);
const unsigned line = lineNumber;
const unsigned column = positionInBlock + 1; const uint line = lineNumber;
const uint column = positionInBlock + 1;
if (!resolveTarget)
return link;
ClangEditorDocumentProcessor *processor = ClangEditorDocumentProcessor::get( ClangEditorDocumentProcessor *processor = ClangEditorDocumentProcessor::get(
data.filePath().toString()); data.filePath().toString());
if (!processor) if (!processor)
return link; return Link();
if (!resolveTarget)
return linkAtCursor(cursor, data.filePath().toString(), line, column, processor);
QFuture<CppTools::SymbolInfo> info QFuture<CppTools::SymbolInfo> info
= processor->requestFollowSymbol(static_cast<int>(line), = processor->requestFollowSymbol(static_cast<int>(line),
static_cast<int>(column), static_cast<int>(column));
resolveTarget);
if (info.isCanceled()) if (info.isCanceled())
return link; return Link();
while (!info.isFinished()) { while (!info.isFinished()) {
if (info.isCanceled()) if (info.isCanceled())
return link; return Link();
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
} }
CppTools::SymbolInfo result = info.result(); CppTools::SymbolInfo result = info.result();
if (result.failedToFollow)
return link;
// We did not fail but the result is empty // We did not fail but the result is empty
if (result.fileName.isEmpty()) if (result.fileName.isEmpty())
return link; return Link();
return Link(result.fileName, result.startLine, result.startColumn - 1); return Link(result.fileName, result.startLine, result.startColumn - 1);
} }

View File

@@ -158,8 +158,15 @@ void HighlightingMarksReporter::run_internal()
if (isCanceled()) if (isCanceled())
return; return;
for (const auto &highlightingMark : m_highlightingMarks) using ClangBackEnd::HighlightingType;
for (const auto &highlightingMark : m_highlightingMarks) {
const HighlightingType mainType = highlightingMark.types().mainHighlightingType;
if (mainType == HighlightingType::StringLiteral)
continue;
reportChunkWise(toHighlightingResult(highlightingMark)); reportChunkWise(toHighlightingResult(highlightingMark));
}
if (isCanceled()) if (isCanceled())
return; return;

View File

@@ -31,6 +31,7 @@
#include "clangfollowsymbol.h" #include "clangfollowsymbol.h"
#include <coreplugin/editormanager/editormanager.h> #include <coreplugin/editormanager/editormanager.h>
#include <cpptools/cppfollowsymbolundercursor.h>
#include <cpptools/cppmodelmanager.h> #include <cpptools/cppmodelmanager.h>
#include <cpptools/editordocumenthandle.h> #include <cpptools/editordocumenthandle.h>
#include <cpptools/projectinfo.h> #include <cpptools/projectinfo.h>
@@ -72,6 +73,8 @@ ModelManagerSupportClang::ModelManagerSupportClang()
if (useClangFollowSymbol()) if (useClangFollowSymbol())
m_followSymbol.reset(new ClangFollowSymbol); m_followSymbol.reset(new ClangFollowSymbol);
else
m_followSymbol.reset(new CppTools::FollowSymbolUnderCursor);
Core::EditorManager *editorManager = Core::EditorManager::instance(); Core::EditorManager *editorManager = Core::EditorManager::instance();
connect(editorManager, &Core::EditorManager::editorOpened, connect(editorManager, &Core::EditorManager::editorOpened,
@@ -106,9 +109,9 @@ CppTools::CppCompletionAssistProvider *ModelManagerSupportClang::completionAssis
return &m_completionAssistProvider; return &m_completionAssistProvider;
} }
CppTools::FollowSymbolInterface *ModelManagerSupportClang::followSymbolInterface() CppTools::FollowSymbolInterface &ModelManagerSupportClang::followSymbolInterface()
{ {
return m_followSymbol.get(); return *m_followSymbol;
} }
CppTools::BaseEditorDocumentProcessor *ModelManagerSupportClang::editorDocumentProcessor( CppTools::BaseEditorDocumentProcessor *ModelManagerSupportClang::editorDocumentProcessor(

View File

@@ -42,12 +42,11 @@ QT_END_NAMESPACE
namespace Core { class IDocument; } namespace Core { class IDocument; }
namespace TextEditor { class TextEditorWidget; } namespace TextEditor { class TextEditorWidget; }
namespace CppTools { class FollowSymbolInterface; }
namespace ClangCodeModel { namespace ClangCodeModel {
namespace Internal { namespace Internal {
class ClangFollowSymbol;
class ModelManagerSupportClang: class ModelManagerSupportClang:
public QObject, public QObject,
public CppTools::ModelManagerSupport public CppTools::ModelManagerSupport
@@ -61,7 +60,7 @@ public:
CppTools::CppCompletionAssistProvider *completionAssistProvider() override; CppTools::CppCompletionAssistProvider *completionAssistProvider() override;
CppTools::BaseEditorDocumentProcessor *editorDocumentProcessor( CppTools::BaseEditorDocumentProcessor *editorDocumentProcessor(
TextEditor::TextDocument *baseTextDocument) override; TextEditor::TextDocument *baseTextDocument) override;
CppTools::FollowSymbolInterface *followSymbolInterface() override; CppTools::FollowSymbolInterface &followSymbolInterface() override;
IpcCommunicator &ipcCommunicator(); IpcCommunicator &ipcCommunicator();
QString dummyUiHeaderOnDiskDirPath() const; QString dummyUiHeaderOnDiskDirPath() const;
@@ -105,7 +104,7 @@ private:
UiHeaderOnDiskManager m_uiHeaderOnDiskManager; UiHeaderOnDiskManager m_uiHeaderOnDiskManager;
IpcCommunicator m_ipcCommunicator; IpcCommunicator m_ipcCommunicator;
ClangCompletionAssistProvider m_completionAssistProvider; ClangCompletionAssistProvider m_completionAssistProvider;
std::unique_ptr<ClangFollowSymbol> m_followSymbol; std::unique_ptr<CppTools::FollowSymbolInterface> m_followSymbol;
}; };
class ModelManagerSupportProviderClang : public CppTools::ModelManagerSupportProvider class ModelManagerSupportProviderClang : public CppTools::ModelManagerSupportProvider

View File

@@ -70,46 +70,21 @@ QStringList createClangOptions(const ProjectPart::Ptr &pPart, const QString &fil
return createClangOptions(pPart, fileKind); return createClangOptions(pPart, fileKind);
} }
class LibClangOptionsBuilder : public ClangCompilerOptionsBuilder class LibClangOptionsBuilder final : public ClangCompilerOptionsBuilder
{ {
public: public:
static QStringList build(const ProjectPart::Ptr &projectPart, ProjectFile::Kind fileKind) LibClangOptionsBuilder(const ProjectPart &projectPart)
{
if (projectPart.isNull())
return QStringList();
LibClangOptionsBuilder optionsBuilder(*projectPart.data());
optionsBuilder.addWordWidth();
optionsBuilder.addTargetTriple();
optionsBuilder.addLanguageOption(fileKind);
optionsBuilder.addOptionsForLanguage(/*checkForBorlandExtensions*/ true);
optionsBuilder.enableExceptions();
optionsBuilder.addDefineToAvoidIncludingGccOrMinGwIntrinsics();
optionsBuilder.addDefineFloat128ForMingw();
optionsBuilder.addToolchainAndProjectDefines();
optionsBuilder.undefineCppLanguageFeatureMacrosForMsvc2015();
optionsBuilder.addPredefinedMacrosAndHeaderPathsOptions();
optionsBuilder.addWrappedQtHeadersIncludePath();
optionsBuilder.addHeaderPathOptions();
optionsBuilder.addDummyUiHeaderOnDiskIncludePath();
optionsBuilder.addProjectConfigFileInclude();
optionsBuilder.addMsvcCompatibilityVersion();
optionsBuilder.addExtraOptions();
return optionsBuilder.options();
}
private:
LibClangOptionsBuilder(const CppTools::ProjectPart &projectPart)
: ClangCompilerOptionsBuilder(projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR) : ClangCompilerOptionsBuilder(projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR)
{ {
} }
void addExtraOptions() final
{
addDummyUiHeaderOnDiskIncludePath();
ClangCompilerOptionsBuilder::addExtraOptions();
}
private:
void addDummyUiHeaderOnDiskIncludePath() void addDummyUiHeaderOnDiskIncludePath()
{ {
const QString path = ModelManagerSupportClang::instance()->dummyUiHeaderOnDiskDirPath(); const QString path = ModelManagerSupportClang::instance()->dummyUiHeaderOnDiskDirPath();
@@ -125,7 +100,9 @@ private:
*/ */
QStringList createClangOptions(const ProjectPart::Ptr &pPart, ProjectFile::Kind fileKind) QStringList createClangOptions(const ProjectPart::Ptr &pPart, ProjectFile::Kind fileKind)
{ {
return LibClangOptionsBuilder::build(pPart, fileKind); if (!pPart)
return QStringList();
return LibClangOptionsBuilder(*pPart).build(fileKind, CompilerOptionsBuilder::PchUsage::None);
} }
ProjectPart::Ptr projectPartForFile(const QString &filePath) ProjectPart::Ptr projectPartForFile(const QString &filePath)

View File

@@ -108,35 +108,9 @@ HeaderAndSources ProjectUpdater::headerAndSourcesFromProjectPart(
QStringList ProjectUpdater::compilerArguments(CppTools::ProjectPart *projectPart) QStringList ProjectUpdater::compilerArguments(CppTools::ProjectPart *projectPart)
{ {
using CppTools::ClangCompilerOptionsBuilder; using ClangCOBuilder = CppTools::ClangCompilerOptionsBuilder;
ClangCOBuilder builder(*projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR);
ClangCompilerOptionsBuilder builder(*projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR); return builder.build(CppTools::ProjectFile::CXXHeader, ClangCOBuilder::PchUsage::None);
builder.addWordWidth();
builder.addTargetTriple();
builder.addLanguageOption(CppTools::ProjectFile::CXXHeader);
builder.addOptionsForLanguage(/*checkForBorlandExtensions*/ true);
builder.enableExceptions();
builder.addDefineToAvoidIncludingGccOrMinGwIntrinsics();
builder.addDefineFloat128ForMingw();
builder.addToolchainAndProjectDefines();
builder.undefineCppLanguageFeatureMacrosForMsvc2015();
builder.addPredefinedMacrosAndHeaderPathsOptions();
builder.addWrappedQtHeadersIncludePath();
builder.addPrecompiledHeaderOptions(ClangCompilerOptionsBuilder::PchUsage::None);
builder.addHeaderPathOptions();
builder.addProjectConfigFileInclude();
builder.addMsvcCompatibilityVersion();
builder.add("-fmessage-length=0");
builder.add("-fmacro-backtrace-limit=0");
builder.add("-w");
builder.add("-ferror-limit=100000");
return builder.options();
} }
ClangBackEnd::V2::ProjectPartContainer ProjectUpdater::toProjectPartContainer( ClangBackEnd::V2::ProjectPartContainer ProjectUpdater::toProjectPartContainer(

View File

@@ -155,31 +155,8 @@ Utils::SmallStringVector ClangQueryProjectsFindFilter::compilerArguments(CppTool
ClangCompilerOptionsBuilder builder(*projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR); ClangCompilerOptionsBuilder builder(*projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR);
builder.addWordWidth(); return Utils::SmallStringVector(builder.build(fileKind,
builder.addTargetTriple(); ClangCompilerOptionsBuilder::PchUsage::None));
builder.addLanguageOption(fileKind);
builder.addOptionsForLanguage(/*checkForBorlandExtensions*/ true);
builder.enableExceptions();
builder.addDefineToAvoidIncludingGccOrMinGwIntrinsics();
builder.addDefineFloat128ForMingw();
builder.addToolchainAndProjectDefines();
builder.undefineCppLanguageFeatureMacrosForMsvc2015();
builder.addPredefinedMacrosAndHeaderPathsOptions();
builder.addWrappedQtHeadersIncludePath();
builder.addPrecompiledHeaderOptions(ClangCompilerOptionsBuilder::PchUsage::None);
builder.addHeaderPathOptions();
builder.addProjectConfigFileInclude();
builder.addMsvcCompatibilityVersion();
builder.add("-fmessage-length=0");
builder.add("-fmacro-backtrace-limit=0");
builder.add("-w");
builder.add("-ferror-limit=1000000");
return Utils::SmallStringVector(builder.options());
} }
QWidget *ClangQueryProjectsFindFilter::widget() const QWidget *ClangQueryProjectsFindFilter::widget() const

View File

@@ -96,6 +96,7 @@ void ClangRefactoringPlugin::extensionsInitialized()
ExtensionSystem::IPlugin::ShutdownFlag ClangRefactoringPlugin::aboutToShutdown() ExtensionSystem::IPlugin::ShutdownFlag ClangRefactoringPlugin::aboutToShutdown()
{ {
ExtensionSystem::PluginManager::removeObject(&d->qtCreatorfindFilter); ExtensionSystem::PluginManager::removeObject(&d->qtCreatorfindFilter);
CppTools::CppModelManager::setRefactoringEngine(nullptr);
d->refactoringClient.setRefactoringConnectionClient(nullptr); d->refactoringClient.setRefactoringConnectionClient(nullptr);
d->refactoringClient.setRefactoringEngine(nullptr); d->refactoringClient.setRefactoringEngine(nullptr);

View File

@@ -64,12 +64,10 @@ void RefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data,
QString filePath = data.filePath().toString(); QString filePath = data.filePath().toString();
QTextCursor textCursor = data.cursor(); QTextCursor textCursor = data.cursor();
Utils::SmallStringVector commandLine{ClangCompilerOptionsBuilder::build( ClangCompilerOptionsBuilder clangCOBuilder{*projectPart, CLANG_VERSION, CLANG_RESOURCE_DIR};
projectPart, Utils::SmallStringVector commandLine{clangCOBuilder.build(
fileKindInProjectPart(projectPart, filePath), fileKindInProjectPart(projectPart, filePath),
CppTools::getPchUsage(), CppTools::getPchUsage())};
CLANG_VERSION,
CLANG_RESOURCE_DIR)};
commandLine.push_back(filePath); commandLine.push_back(filePath);
@@ -84,6 +82,11 @@ void RefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data,
server.requestSourceLocationsForRenamingMessage(std::move(message)); server.requestSourceLocationsForRenamingMessage(std::move(message));
} }
void RefactoringEngine::startGlobalRenaming(const CppTools::CursorInEditor &)
{
// TODO: implement
}
bool RefactoringEngine::isUsable() const bool RefactoringEngine::isUsable() const
{ {
return server.isUsable(); return server.isUsable();

View File

@@ -42,6 +42,7 @@ public:
void startLocalRenaming(const CppTools::CursorInEditor &data, void startLocalRenaming(const CppTools::CursorInEditor &data,
CppTools::ProjectPart *projectPart, CppTools::ProjectPart *projectPart,
RenameCallback &&renameSymbolsCallback) override; RenameCallback &&renameSymbolsCallback) override;
void startGlobalRenaming(const CppTools::CursorInEditor &data) override;
bool isUsable() const override; bool isUsable() const override;
void setUsable(bool isUsable); void setUsable(bool isUsable);

View File

@@ -39,24 +39,25 @@ class SourceLocations
public: public:
struct Location struct Location
{ {
qint64 sourceId; Location(qint64 sourceId, qint64 line, qint64 column)
qint64 line; : sourceId(sourceId), line(line), column(column)
qint64 column; {}
qint64 sourceId;
qint64 line;
qint64 column;
}; };
struct Source struct Source
{ {
Source(qint64 sourceId, Utils::PathString &&sourcePath)
: sourceId(sourceId), sourcePath(std::move(sourcePath))
{}
qint64 sourceId; qint64 sourceId;
Utils::PathString sourcePath; Utils::PathString sourcePath;
}; };
enum LocationGetter
{
SourceId = 0,
Line,
Column
};
std::vector<Location> locations; std::vector<Location> locations;
std::unordered_map<qint64, Utils::PathString> sources; std::unordered_map<qint64, Utils::PathString> sources;
}; };

View File

@@ -52,7 +52,7 @@ public:
const std::size_t reserveSize = 128; const std::size_t reserveSize = 128;
auto locations = locationsStatement.template structValues<Location, qint64, qint64, qint64>( auto locations = locationsStatement.template values<Location, 3>(
reserveSize, reserveSize,
filePath, filePath,
line, line,
@@ -62,7 +62,7 @@ public:
ReadStatement &sourcesStatement = m_statementFactory.selectSourcePathForId; ReadStatement &sourcesStatement = m_statementFactory.selectSourcePathForId;
auto sources = sourcesStatement.template structValues<Source, qint64, Utils::PathString>( auto sources = sourcesStatement.template values<Source, 2>(
reserveSize, reserveSize,
sourceIds); sourceIds);

View File

@@ -167,7 +167,7 @@ static QList<Target *> validTargets(Project *project)
const ToolChain * const toolchain = ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID); const ToolChain * const toolchain = ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
QTC_ASSERT(toolchain, return false); QTC_ASSERT(toolchain, return false);
bool hasClangExecutable; bool hasClangExecutable;
clangExecutableFromSettings(toolchain->typeId(), &hasClangExecutable); clangExecutableFromSettings(&hasClangExecutable);
if (!hasClangExecutable) { if (!hasClangExecutable) {
qWarning("Project \"%s\": Skipping target \"%s\" since no suitable clang was found for the toolchain.", qWarning("Project \"%s\": Skipping target \"%s\" since no suitable clang was found for the toolchain.",
qPrintable(projectFileName), qPrintable(projectFileName),

View File

@@ -38,7 +38,7 @@
#include <coreplugin/progressmanager/futureprogress.h> #include <coreplugin/progressmanager/futureprogress.h>
#include <coreplugin/progressmanager/progressmanager.h> #include <coreplugin/progressmanager/progressmanager.h>
#include <cpptools/compileroptionsbuilder.h> #include <cpptools/clangcompileroptionsbuilder.h>
#include <cpptools/cppmodelmanager.h> #include <cpptools/cppmodelmanager.h>
#include <cpptools/cppprojectfile.h> #include <cpptools/cppprojectfile.h>
#include <cpptools/cpptoolsreuse.h> #include <cpptools/cpptoolsreuse.h>
@@ -161,8 +161,7 @@ static void prependTargetTripleIfNotIncludedAndNotEmpty(QStringList *arguments,
} }
// Removes (1) inputFile (2) -o <somePath>. // Removes (1) inputFile (2) -o <somePath>.
QStringList inputAndOutputArgumentsRemoved(const QString &inputFile, const QStringList &arguments, QStringList inputAndOutputArgumentsRemoved(const QString &inputFile, const QStringList &arguments)
bool isMsvc)
{ {
QStringList newArguments; QStringList newArguments;
@@ -174,9 +173,6 @@ QStringList inputAndOutputArgumentsRemoved(const QString &inputFile, const QStri
} else if (argument == QLatin1String("-o")) { } else if (argument == QLatin1String("-o")) {
skip = true; skip = true;
continue; continue;
} else if (isMsvc && argument == QLatin1String("-target")) {
skip = true;
continue;
} else if (QDir::fromNativeSeparators(argument) == inputFile) { } else if (QDir::fromNativeSeparators(argument) == inputFile) {
continue; // TODO: Let it in? continue; // TODO: Let it in?
} }
@@ -188,55 +184,11 @@ QStringList inputAndOutputArgumentsRemoved(const QString &inputFile, const QStri
return newArguments; return newArguments;
} }
static QString createLanguageOptionMsvc(ProjectFile::Kind fileKind) class ClangStaticAnalyzerOptionsBuilder final : public ClangCompilerOptionsBuilder
{
switch (fileKind) {
case ProjectFile::CHeader:
case ProjectFile::CSource:
return QLatin1String("/TC");
break;
case ProjectFile::CXXHeader:
case ProjectFile::CXXSource:
return QLatin1String("/TP");
break;
default:
break;
}
return QString();
}
class ClangStaticAnalyzerOptionsBuilder : public CompilerOptionsBuilder
{ {
public: public:
static QStringList build(const CppTools::ProjectPart &projectPart,
CppTools::ProjectFile::Kind fileKind,
PchUsage pchUsage)
{
ClangStaticAnalyzerOptionsBuilder optionsBuilder(projectPart);
optionsBuilder.addWordWidth();
optionsBuilder.addTargetTriple();
optionsBuilder.addLanguageOption(fileKind);
optionsBuilder.addOptionsForLanguage(false);
optionsBuilder.enableExceptions();
optionsBuilder.addDefineFloat128ForMingw();
optionsBuilder.addDefineToAvoidIncludingGccOrMinGwIntrinsics();
const Core::Id type = projectPart.toolchainType;
if (type != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID)
optionsBuilder.addMacros(projectPart.toolChainMacros);
optionsBuilder.addMacros(projectPart.projectMacros);
optionsBuilder.undefineClangVersionMacrosForMsvc();
optionsBuilder.undefineCppLanguageFeatureMacrosForMsvc2015();
optionsBuilder.addHeaderPathOptions();
optionsBuilder.addPrecompiledHeaderOptions(pchUsage);
optionsBuilder.addMsvcCompatibilityVersion();
return optionsBuilder.options();
}
ClangStaticAnalyzerOptionsBuilder(const CppTools::ProjectPart &projectPart) ClangStaticAnalyzerOptionsBuilder(const CppTools::ProjectPart &projectPart)
: CompilerOptionsBuilder(projectPart) : ClangCompilerOptionsBuilder(projectPart)
, m_isMsvcToolchain(m_projectPart.toolchainType , m_isMsvcToolchain(m_projectPart.toolchainType
== ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID)
, m_isMinGWToolchain(m_projectPart.toolchainType , m_isMinGWToolchain(m_projectPart.toolchainType
@@ -244,91 +196,28 @@ public:
{ {
} }
public: bool excludeHeaderPath(const QString &headerPath) const final
bool excludeHeaderPath(const QString &headerPath) const override
{ {
if (CompilerOptionsBuilder::excludeHeaderPath(headerPath))
return true;
if (m_isMinGWToolchain && headerPath.contains(m_projectPart.toolChainTargetTriple)) if (m_isMinGWToolchain && headerPath.contains(m_projectPart.toolChainTargetTriple))
return true; return true;
return false; return ClangCompilerOptionsBuilder::excludeHeaderPath(headerPath);
} }
void undefineClangVersionMacrosForMsvc() void addPredefinedHeaderPathsOptions() final
{ {
if (m_projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) { add("-undef");
static QStringList macroNames { if (m_isMsvcToolchain) {
"__clang__", // exclude default clang path to use msvc includes
"__clang_major__", add("-nostdinc");
"__clang_minor__", add("-nostdlibinc");
"__clang_patchlevel__",
"__clang_version__"
};
foreach (const QString &macroName, macroNames)
add(QLatin1String("/U") + macroName);
} }
} }
private: void addExtraOptions() final {}
void addTargetTriple() override
{
// For MSVC toolchains we use clang-cl.exe, so there is nothing to do here since
// 1) clang-cl.exe does not understand the "-triple" option
// 2) clang-cl.exe already hardcodes the right triple value (even if built with mingw)
if (!m_isMsvcToolchain)
CompilerOptionsBuilder::addTargetTriple();
}
void addLanguageOption(ProjectFile::Kind fileKind) override void addWrappedQtHeadersIncludePath() final
{ {
if (m_isMsvcToolchain) // Empty, analyzer doesn't need them
add(createLanguageOptionMsvc(fileKind));
else
CompilerOptionsBuilder::addLanguageOption(fileKind);
}
void addOptionsForLanguage(bool checkForBorlandExtensions) override
{
if (m_isMsvcToolchain)
return;
CompilerOptionsBuilder::addOptionsForLanguage(checkForBorlandExtensions);
}
QString includeOption() const override
{
if (m_isMsvcToolchain)
return QLatin1String("/FI");
return CompilerOptionsBuilder::includeOption();
}
QString includeDirOption() const override
{
if (m_isMsvcToolchain)
return QLatin1String("/I");
return CompilerOptionsBuilder::includeDirOption();
}
QString defineOption() const override
{
if (m_isMsvcToolchain)
return QLatin1String("/D");
return CompilerOptionsBuilder::defineOption();
}
QString undefineOption() const override
{
if (m_isMsvcToolchain)
return QLatin1String("/U");
return CompilerOptionsBuilder::undefineOption();
}
void enableExceptions() override
{
if (m_isMsvcToolchain)
add(QLatin1String("/EHsc"));
else
CompilerOptionsBuilder::enableExceptions();
} }
private: private:
@@ -383,7 +272,7 @@ static QStringList tweakedArguments(const ProjectPart &projectPart,
{ {
const bool isMsvc = projectPart.toolchainType const bool isMsvc = projectPart.toolchainType
== ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID; == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID;
QStringList newArguments = inputAndOutputArgumentsRemoved(filePath, arguments, isMsvc); QStringList newArguments = inputAndOutputArgumentsRemoved(filePath, arguments);
prependWordWidthArgumentIfNotIncluded(&newArguments, projectPart.toolChainWordWidth); prependWordWidthArgumentIfNotIncluded(&newArguments, projectPart.toolChainWordWidth);
if (!isMsvc) if (!isMsvc)
prependTargetTripleIfNotIncludedAndNotEmpty(&newArguments, targetTriple); prependTargetTripleIfNotIncludedAndNotEmpty(&newArguments, targetTriple);
@@ -434,7 +323,7 @@ static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QVector<ProjectPart::Pt
AnalyzeUnits unitsToAnalyze; AnalyzeUnits unitsToAnalyze;
foreach (const ProjectPart::Ptr &projectPart, projectParts) { foreach (const ProjectPart::Ptr &projectPart, projectParts) {
if (!projectPart->selectedForBuilding) if (!projectPart->selectedForBuilding || !projectPart.data())
continue; continue;
foreach (const ProjectFile &file, projectPart->files) { foreach (const ProjectFile &file, projectPart->files) {
@@ -445,7 +334,7 @@ static AnalyzeUnits unitsToAnalyzeFromProjectParts(const QVector<ProjectPart::Pt
if (ProjectFile::isSource(file.kind)) { if (ProjectFile::isSource(file.kind)) {
const CompilerOptionsBuilder::PchUsage pchUsage = CppTools::getPchUsage(); const CompilerOptionsBuilder::PchUsage pchUsage = CppTools::getPchUsage();
const QStringList arguments const QStringList arguments
= ClangStaticAnalyzerOptionsBuilder::build(*projectPart.data(), file.kind, pchUsage); = ClangStaticAnalyzerOptionsBuilder(*projectPart).build(file.kind, pchUsage);
unitsToAnalyze << AnalyzeUnit(file.path, arguments); unitsToAnalyze << AnalyzeUnit(file.path, arguments);
} }
} }
@@ -501,21 +390,6 @@ static QDebug operator<<(QDebug debug, const AnalyzeUnits &analyzeUnits)
return debug; return debug;
} }
static QString executableForVersionCheck(Core::Id toolchainType, const QString &executable)
{
if (toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) {
const QString suffix = QLatin1String("-cl.exe");
if (executable.endsWith(suffix, Utils::HostOsInfo::fileNameCaseSensitivity())) {
QString modified = executable;
modified.chop(suffix.length());
modified.append(QLatin1String(".exe"));
return modified;
}
}
return executable;
}
void ClangStaticAnalyzerToolRunner::start() void ClangStaticAnalyzerToolRunner::start()
{ {
m_success = false; m_success = false;
@@ -532,8 +406,7 @@ void ClangStaticAnalyzerToolRunner::start()
// Check clang executable // Check clang executable
bool isValidClangExecutable; bool isValidClangExecutable;
const QString executable = clangExecutableFromSettings(m_toolChainType, const QString executable = clangExecutableFromSettings(&isValidClangExecutable);
&isValidClangExecutable);
if (!isValidClangExecutable) { if (!isValidClangExecutable) {
const QString errorMessage = tr("Clang Static Analyzer: Invalid executable \"%1\", stop.") const QString errorMessage = tr("Clang Static Analyzer: Invalid executable \"%1\", stop.")
.arg(executable); .arg(executable);
@@ -545,13 +418,12 @@ void ClangStaticAnalyzerToolRunner::start()
} }
// Check clang version // Check clang version
const QString versionCheckExecutable = executableForVersionCheck(m_toolChainType, executable); const ClangExecutableVersion version = clangExecutableVersion(executable);
const ClangExecutableVersion version = clangExecutableVersion(versionCheckExecutable);
if (!version.isValid()) { if (!version.isValid()) {
const QString warningMessage const QString warningMessage
= tr("Clang Static Analyzer: Running with possibly unsupported version, " = tr("Clang Static Analyzer: Running with possibly unsupported version, "
"could not determine version from executable \"%1\".") "could not determine version from executable \"%1\".")
.arg(versionCheckExecutable); .arg(executable);
appendMessage(warningMessage, Utils::StdErrFormat); appendMessage(warningMessage, Utils::StdErrFormat);
TaskHub::addTask(Task::Warning, warningMessage, Debugger::Constants::ANALYZERTASK_ID); TaskHub::addTask(Task::Warning, warningMessage, Debugger::Constants::ANALYZERTASK_ID);
TaskHub::requestPopup(); TaskHub::requestPopup();

View File

@@ -58,7 +58,7 @@ void ClangStaticAnalyzerUnitTests::initTestCase()
if (!toolchain) if (!toolchain)
QSKIP("This test requires that there is a kit with a toolchain."); QSKIP("This test requires that there is a kit with a toolchain.");
bool hasClangExecutable; bool hasClangExecutable;
clangExecutableFromSettings(toolchain->typeId(), &hasClangExecutable); clangExecutableFromSettings(&hasClangExecutable);
if (!hasClangExecutable) if (!hasClangExecutable)
QSKIP("No clang suitable for analyzing found"); QSKIP("No clang suitable for analyzing found");

View File

@@ -50,7 +50,7 @@ static bool isFileExecutable(const QString &executablePath)
namespace ClangStaticAnalyzer { namespace ClangStaticAnalyzer {
namespace Internal { namespace Internal {
QString clangExecutableFromSettings(Core::Id toolchainType, bool *isValid) QString clangExecutableFromSettings(bool *isValid)
{ {
QString executable = ClangStaticAnalyzerSettings::instance()->clangExecutable(); QString executable = ClangStaticAnalyzerSettings::instance()->clangExecutable();
if (executable.isEmpty()) { if (executable.isEmpty()) {
@@ -62,14 +62,6 @@ QString clangExecutableFromSettings(Core::Id toolchainType, bool *isValid)
const Qt::CaseSensitivity caseSensitivity = Utils::HostOsInfo::fileNameCaseSensitivity(); const Qt::CaseSensitivity caseSensitivity = Utils::HostOsInfo::fileNameCaseSensitivity();
const bool hasSuffix = executable.endsWith(hostExeSuffix, caseSensitivity); const bool hasSuffix = executable.endsWith(hostExeSuffix, caseSensitivity);
if (toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) {
if (hasSuffix)
executable.chop(hostExeSuffix.length());
executable.append(QLatin1String("-cl"));
if (hasSuffix)
executable.append(hostExeSuffix);
}
const QFileInfo fileInfo = QFileInfo(executable); const QFileInfo fileInfo = QFileInfo(executable);
if (fileInfo.isAbsolute()) { if (fileInfo.isAbsolute()) {
if (!hasSuffix) if (!hasSuffix)

View File

@@ -41,7 +41,7 @@ namespace Internal {
bool isClangExecutableUsable(const QString &filePath, QString *errorMessage = 0); bool isClangExecutableUsable(const QString &filePath, QString *errorMessage = 0);
QString clangExecutableFromSettings(Core::Id toolchainType, bool *isValid); QString clangExecutableFromSettings(bool *isValid);
QString createFullLocationString(const Debugger::DiagnosticLocation &location); QString createFullLocationString(const Debugger::DiagnosticLocation &location);

View File

@@ -44,6 +44,7 @@
#include <utils/fileutils.h> #include <utils/fileutils.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QDir>
#include <QMessageBox> #include <QMessageBox>
#include <QPushButton> #include <QPushButton>
#include <QSet> #include <QSet>
@@ -72,12 +73,22 @@ BuildDirManager::~BuildDirManager() = default;
const Utils::FileName BuildDirManager::workDirectory() const const Utils::FileName BuildDirManager::workDirectory() const
{ {
const Utils::FileName bdir = m_buildConfiguration->buildDirectory(); const Utils::FileName bdir = m_buildConfiguration->buildDirectory();
if (bdir.exists()) const CMakeTool *cmake = CMakeKitInformation::cmakeTool(m_buildConfiguration->target()->kit());
if (bdir.exists()) {
return bdir; return bdir;
} else {
if (cmake && cmake->autoCreateBuildDirectory()) {
if (!QDir().mkpath(bdir.toString()))
emitErrorOccured(tr("Failed to create build directory \"%1\".").arg(bdir.toUserOutput()));
return bdir;
}
}
if (!m_tempDir) { if (!m_tempDir) {
m_tempDir.reset(new Utils::TemporaryDirectory("qtc-cmake-XXXXXXXX")); m_tempDir.reset(new Utils::TemporaryDirectory("qtc-cmake-XXXXXXXX"));
if (!m_tempDir->isValid()) if (!m_tempDir->isValid()) {
emitErrorOccured(tr("Failed to create temporary directory \"%1\".").arg(m_tempDir->path())); emitErrorOccured(tr("Failed to create temporary directory \"%1\".")
.arg(QDir::toNativeSeparators(m_tempDir->path())));
}
} }
return Utils::FileName::fromString(m_tempDir->path()); return Utils::FileName::fromString(m_tempDir->path());
} }

View File

@@ -378,6 +378,33 @@ void CMakeBuildSettingsWidget::updateSelection(const QModelIndex &current, const
m_editButton->setEnabled(currentModelIndex.flags().testFlag(Qt::ItemIsEditable)); m_editButton->setEnabled(currentModelIndex.flags().testFlag(Qt::ItemIsEditable));
} }
QAction *CMakeBuildSettingsWidget::createForceAction(int type, const QModelIndex &idx)
{
ConfigModel::DataItem::Type t = static_cast<ConfigModel::DataItem::Type>(type);
QString typeString;
switch (type) {
case ConfigModel::DataItem::BOOLEAN:
typeString = tr("bool", "display string for cmake type BOOLEAN");
break;
case ConfigModel::DataItem::FILE:
typeString = tr("file", "display string for cmake type FILE");
break;
case ConfigModel::DataItem::DIRECTORY:
typeString = tr("directory", "display string for cmake type DIRECTORY");
break;
case ConfigModel::DataItem::STRING:
typeString = tr("string", "display string for cmake type STRING");
break;
case ConfigModel::DataItem::UNKNOWN:
return nullptr;
}
QAction *forceAction = new QAction(tr("Force to %1").arg(typeString), nullptr);
forceAction->setEnabled(m_configModel->canForceTo(idx, t));
connect(forceAction, &QAction::triggered,
this, [this, idx, t]() { m_configModel->forceTo(idx, t); });
return forceAction;
}
bool CMakeBuildSettingsWidget::eventFilter(QObject *target, QEvent *event) bool CMakeBuildSettingsWidget::eventFilter(QObject *target, QEvent *event)
{ {
// handle context menu events: // handle context menu events:
@@ -392,10 +419,15 @@ bool CMakeBuildSettingsWidget::eventFilter(QObject *target, QEvent *event)
QMenu *menu = new QMenu(this); QMenu *menu = new QMenu(this);
connect(menu, &QMenu::triggered, menu, &QMenu::deleteLater); connect(menu, &QMenu::triggered, menu, &QMenu::deleteLater);
QAction *forceToStringAction = new QAction(tr("Force to String"), nullptr); QAction *action = nullptr;
forceToStringAction->setEnabled(m_configModel->canForceToString(idx)); if ((action = createForceAction(ConfigModel::DataItem::BOOLEAN, idx)))
menu->addAction(forceToStringAction); menu->addAction(action);
connect(forceToStringAction, &QAction::triggered, this, [this, idx]() { m_configModel->forceToString(idx); }); if ((action = createForceAction(ConfigModel::DataItem::FILE, idx)))
menu->addAction(action);
if ((action = createForceAction(ConfigModel::DataItem::DIRECTORY, idx)))
menu->addAction(action);
if ((action = createForceAction(ConfigModel::DataItem::STRING, idx)))
menu->addAction(action);
menu->move(e->globalPos()); menu->move(e->globalPos());
menu->show(); menu->show();

View File

@@ -65,6 +65,7 @@ private:
void updateFromKit(); void updateFromKit();
void updateSelection(const QModelIndex &current, const QModelIndex &previous); void updateSelection(const QModelIndex &current, const QModelIndex &previous);
QAction *createForceAction(int type, const QModelIndex &idx);
bool eventFilter(QObject *target, QEvent *event); bool eventFilter(QObject *target, QEvent *event);

View File

@@ -152,7 +152,7 @@ void CMakeProject::updateProjectData(CMakeBuildConfiguration *bc)
} }
updateApplicationAndDeploymentTargets(); updateApplicationAndDeploymentTargets();
t->updateDefaultRunConfigurations(); updateTargetRunConfigurations(t);
createGeneratedCodeModelSupport(); createGeneratedCodeModelSupport();
@@ -448,6 +448,34 @@ QStringList CMakeProject::filesGeneratedFrom(const QString &sourceFile) const
} }
} }
void CMakeProject::updateTargetRunConfigurations(Target *t)
{
// *Update* existing runconfigurations (no need to update new ones!):
QHash<QString, const CMakeBuildTarget *> buildTargetHash;
const QList<CMakeBuildTarget> buildTargetList = buildTargets();
foreach (const CMakeBuildTarget &bt, buildTargetList) {
if (bt.targetType != ExecutableType || bt.executable.isEmpty())
continue;
buildTargetHash.insert(bt.title, &bt);
}
foreach (RunConfiguration *rc, t->runConfigurations()) {
auto cmakeRc = qobject_cast<CMakeRunConfiguration *>(rc);
if (!cmakeRc)
continue;
auto btIt = buildTargetHash.constFind(cmakeRc->title());
if (btIt != buildTargetHash.constEnd()) {
cmakeRc->setExecutable(btIt.value()->executable.toString());
cmakeRc->setBaseWorkingDirectory(btIt.value()->workingDirectory);
}
}
// create new and remove obsolete RCs using the factories
t->updateDefaultRunConfigurations();
}
void CMakeProject::updateApplicationAndDeploymentTargets() void CMakeProject::updateApplicationAndDeploymentTargets()
{ {
Target *t = activeTarget(); Target *t = activeTarget();

View File

@@ -123,6 +123,7 @@ private:
void createGeneratedCodeModelSupport(); void createGeneratedCodeModelSupport();
QStringList filesGeneratedFrom(const QString &sourceFile) const final; QStringList filesGeneratedFrom(const QString &sourceFile) const final;
void updateTargetRunConfigurations(ProjectExplorer::Target *t);
void updateApplicationAndDeploymentTargets(); void updateApplicationAndDeploymentTargets();
ProjectExplorer::Target *m_connectedTarget = nullptr; ProjectExplorer::Target *m_connectedTarget = nullptr;

View File

@@ -66,13 +66,13 @@ public:
CMakeToolTreeItem *cmakeToolItem(const Core::Id &id) const; CMakeToolTreeItem *cmakeToolItem(const Core::Id &id) const;
CMakeToolTreeItem *cmakeToolItem(const QModelIndex &index) const; CMakeToolTreeItem *cmakeToolItem(const QModelIndex &index) const;
QModelIndex addCMakeTool(const QString &name, const FileName &executable, const bool autoRun, const bool isAutoDetected); QModelIndex addCMakeTool(const QString &name, const FileName &executable, const bool autoRun, const bool autoCreate, const bool isAutoDetected);
void addCMakeTool(const CMakeTool *item, bool changed); void addCMakeTool(const CMakeTool *item, bool changed);
TreeItem *autoGroupItem() const; TreeItem *autoGroupItem() const;
TreeItem *manualGroupItem() const; TreeItem *manualGroupItem() const;
void reevaluateChangedFlag(CMakeToolTreeItem *item) const; void reevaluateChangedFlag(CMakeToolTreeItem *item) const;
void updateCMakeTool(const Core::Id &id, const QString &displayName, const FileName &executable, void updateCMakeTool(const Core::Id &id, const QString &displayName, const FileName &executable,
bool autoRun); bool autoRun, bool autoCreate);
void removeCMakeTool(const Core::Id &id); void removeCMakeTool(const Core::Id &id);
void apply(); void apply();
@@ -95,16 +95,18 @@ public:
m_name(item->displayName()), m_name(item->displayName()),
m_executable(item->cmakeExecutable()), m_executable(item->cmakeExecutable()),
m_isAutoRun(item->isAutoRun()), m_isAutoRun(item->isAutoRun()),
m_autoCreateBuildDirectory(item->autoCreateBuildDirectory()),
m_autodetected(item->isAutoDetected()), m_autodetected(item->isAutoDetected()),
m_changed(changed) m_changed(changed)
{} {}
CMakeToolTreeItem(const QString &name, const Utils::FileName &executable, CMakeToolTreeItem(const QString &name, const Utils::FileName &executable,
bool autoRun, bool autodetected) : bool autoRun, bool autoCreate, bool autodetected) :
m_id(Core::Id::fromString(QUuid::createUuid().toString())), m_id(Core::Id::fromString(QUuid::createUuid().toString())),
m_name(name), m_name(name),
m_executable(executable), m_executable(executable),
m_isAutoRun(autoRun), m_isAutoRun(autoRun),
m_autoCreateBuildDirectory(autoCreate),
m_autodetected(autodetected), m_autodetected(autodetected),
m_changed(true) m_changed(true)
{} {}
@@ -143,6 +145,7 @@ public:
QString m_name; QString m_name;
FileName m_executable; FileName m_executable;
bool m_isAutoRun = true; bool m_isAutoRun = true;
bool m_autoCreateBuildDirectory = false;
bool m_autodetected = false; bool m_autodetected = false;
bool m_changed = true; bool m_changed = true;
}; };
@@ -166,9 +169,10 @@ CMakeToolItemModel::CMakeToolItemModel()
} }
QModelIndex CMakeToolItemModel::addCMakeTool(const QString &name, const FileName &executable, QModelIndex CMakeToolItemModel::addCMakeTool(const QString &name, const FileName &executable,
const bool autoRun, const bool isAutoDetected) const bool autoRun, const bool autoCreate,
const bool isAutoDetected)
{ {
CMakeToolTreeItem *item = new CMakeToolTreeItem(name, executable, autoRun, isAutoDetected); CMakeToolTreeItem *item = new CMakeToolTreeItem(name, executable, autoRun, autoCreate, isAutoDetected);
if (isAutoDetected) if (isAutoDetected)
autoGroupItem()->appendChild(item); autoGroupItem()->appendChild(item);
else else
@@ -219,7 +223,8 @@ void CMakeToolItemModel::reevaluateChangedFlag(CMakeToolTreeItem *item) const
} }
void CMakeToolItemModel::updateCMakeTool(const Core::Id &id, const QString &displayName, void CMakeToolItemModel::updateCMakeTool(const Core::Id &id, const QString &displayName,
const FileName &executable, bool autoRun) const FileName &executable, bool autoRun,
bool autoCreate)
{ {
CMakeToolTreeItem *treeItem = cmakeToolItem(id); CMakeToolTreeItem *treeItem = cmakeToolItem(id);
QTC_ASSERT(treeItem, return); QTC_ASSERT(treeItem, return);
@@ -227,6 +232,7 @@ void CMakeToolItemModel::updateCMakeTool(const Core::Id &id, const QString &disp
treeItem->m_name = displayName; treeItem->m_name = displayName;
treeItem->m_executable = executable; treeItem->m_executable = executable;
treeItem->m_isAutoRun = autoRun; treeItem->m_isAutoRun = autoRun;
treeItem->m_autoCreateBuildDirectory = autoCreate;
reevaluateChangedFlag(treeItem); reevaluateChangedFlag(treeItem);
} }
@@ -262,6 +268,7 @@ void CMakeToolItemModel::apply()
cmake->setDisplayName(item->m_name); cmake->setDisplayName(item->m_name);
cmake->setCMakeExecutable(item->m_executable); cmake->setCMakeExecutable(item->m_executable);
cmake->setAutorun(item->m_isAutoRun); cmake->setAutorun(item->m_isAutoRun);
cmake->setAutoCreateBuildDirectory(item->m_autoCreateBuildDirectory);
} else { } else {
toRegister.append(item); toRegister.append(item);
} }
@@ -329,6 +336,7 @@ private:
CMakeToolItemModel *m_model; CMakeToolItemModel *m_model;
QLineEdit *m_displayNameLineEdit; QLineEdit *m_displayNameLineEdit;
QCheckBox *m_autoRunCheckBox; QCheckBox *m_autoRunCheckBox;
QCheckBox *m_autoCreateBuildDirectoryCheckBox;
PathChooser *m_binaryChooser; PathChooser *m_binaryChooser;
Core::Id m_id; Core::Id m_id;
bool m_loadingItem; bool m_loadingItem;
@@ -349,11 +357,16 @@ CMakeToolItemConfigWidget::CMakeToolItemConfigWidget(CMakeToolItemModel *model)
m_autoRunCheckBox->setText(tr("Autorun CMake")); m_autoRunCheckBox->setText(tr("Autorun CMake"));
m_autoRunCheckBox->setToolTip(tr("Automatically run CMake after changes to CMake project files.")); m_autoRunCheckBox->setToolTip(tr("Automatically run CMake after changes to CMake project files."));
m_autoCreateBuildDirectoryCheckBox = new QCheckBox;
m_autoCreateBuildDirectoryCheckBox->setText(tr("Auto-create build directories"));
m_autoCreateBuildDirectoryCheckBox->setToolTip(tr("Automatically create build directories for CMake projects."));
QFormLayout *formLayout = new QFormLayout(this); QFormLayout *formLayout = new QFormLayout(this);
formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
formLayout->addRow(new QLabel(tr("Name:")), m_displayNameLineEdit); formLayout->addRow(new QLabel(tr("Name:")), m_displayNameLineEdit);
formLayout->addRow(new QLabel(tr("Path:")), m_binaryChooser); formLayout->addRow(new QLabel(tr("Path:")), m_binaryChooser);
formLayout->addRow(m_autoRunCheckBox); formLayout->addRow(m_autoRunCheckBox);
formLayout->addRow(m_autoCreateBuildDirectoryCheckBox);
connect(m_binaryChooser, &PathChooser::rawPathChanged, connect(m_binaryChooser, &PathChooser::rawPathChanged,
this, &CMakeToolItemConfigWidget::store); this, &CMakeToolItemConfigWidget::store);
@@ -361,13 +374,16 @@ CMakeToolItemConfigWidget::CMakeToolItemConfigWidget(CMakeToolItemModel *model)
this, &CMakeToolItemConfigWidget::store); this, &CMakeToolItemConfigWidget::store);
connect(m_autoRunCheckBox, &QCheckBox::toggled, connect(m_autoRunCheckBox, &QCheckBox::toggled,
this, &CMakeToolItemConfigWidget::store); this, &CMakeToolItemConfigWidget::store);
connect(m_autoCreateBuildDirectoryCheckBox, &QCheckBox::toggled,
this, &CMakeToolItemConfigWidget::store);
} }
void CMakeToolItemConfigWidget::store() const void CMakeToolItemConfigWidget::store() const
{ {
if (!m_loadingItem && m_id.isValid()) if (!m_loadingItem && m_id.isValid())
m_model->updateCMakeTool(m_id, m_displayNameLineEdit->text(), m_binaryChooser->fileName(), m_model->updateCMakeTool(m_id, m_displayNameLineEdit->text(), m_binaryChooser->fileName(),
m_autoRunCheckBox->checkState() == Qt::Checked); m_autoRunCheckBox->checkState() == Qt::Checked,
m_autoCreateBuildDirectoryCheckBox->checkState() == Qt::Checked);
} }
void CMakeToolItemConfigWidget::load(const CMakeToolTreeItem *item) void CMakeToolItemConfigWidget::load(const CMakeToolTreeItem *item)
@@ -387,6 +403,7 @@ void CMakeToolItemConfigWidget::load(const CMakeToolTreeItem *item)
m_binaryChooser->setFileName(item->m_executable); m_binaryChooser->setFileName(item->m_executable);
m_autoRunCheckBox->setChecked(item->m_isAutoRun); m_autoRunCheckBox->setChecked(item->m_isAutoRun);
m_autoCreateBuildDirectoryCheckBox->setChecked(item->m_autoCreateBuildDirectory);
m_id = item->m_id; m_id = item->m_id;
m_loadingItem = false; m_loadingItem = false;
@@ -492,7 +509,8 @@ void CMakeToolConfigWidget::cloneCMakeTool()
QModelIndex newItem = m_model.addCMakeTool(tr("Clone of %1").arg(m_currentItem->m_name), QModelIndex newItem = m_model.addCMakeTool(tr("Clone of %1").arg(m_currentItem->m_name),
m_currentItem->m_executable, m_currentItem->m_executable,
m_currentItem->m_isAutoRun, false); m_currentItem->m_isAutoRun,
m_currentItem->m_autoCreateBuildDirectory, false);
m_cmakeToolsView->setCurrentIndex(newItem); m_cmakeToolsView->setCurrentIndex(newItem);
} }
@@ -500,7 +518,7 @@ void CMakeToolConfigWidget::cloneCMakeTool()
void CMakeToolConfigWidget::addCMakeTool() void CMakeToolConfigWidget::addCMakeTool()
{ {
QModelIndex newItem = m_model.addCMakeTool(m_model.uniqueDisplayName(tr("New CMake")), QModelIndex newItem = m_model.addCMakeTool(m_model.uniqueDisplayName(tr("New CMake")),
FileName(), true, false); FileName(), true, false, false);
m_cmakeToolsView->setCurrentIndex(newItem); m_cmakeToolsView->setCurrentIndex(newItem);
} }

View File

@@ -46,6 +46,7 @@ const char CMAKE_INFORMATION_ID[] = "Id";
const char CMAKE_INFORMATION_COMMAND[] = "Binary"; const char CMAKE_INFORMATION_COMMAND[] = "Binary";
const char CMAKE_INFORMATION_DISPLAYNAME[] = "DisplayName"; const char CMAKE_INFORMATION_DISPLAYNAME[] = "DisplayName";
const char CMAKE_INFORMATION_AUTORUN[] = "AutoRun"; const char CMAKE_INFORMATION_AUTORUN[] = "AutoRun";
const char CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY[] = "AutoCreateBuildDirectory";
const char CMAKE_INFORMATION_AUTODETECTED[] = "AutoDetected"; const char CMAKE_INFORMATION_AUTODETECTED[] = "AutoDetected";
@@ -68,6 +69,7 @@ CMakeTool::CMakeTool(const QVariantMap &map, bool fromSdk) : m_isAutoDetected(fr
m_id = Core::Id::fromSetting(map.value(CMAKE_INFORMATION_ID)); m_id = Core::Id::fromSetting(map.value(CMAKE_INFORMATION_ID));
m_displayName = map.value(CMAKE_INFORMATION_DISPLAYNAME).toString(); m_displayName = map.value(CMAKE_INFORMATION_DISPLAYNAME).toString();
m_isAutoRun = map.value(CMAKE_INFORMATION_AUTORUN, true).toBool(); m_isAutoRun = map.value(CMAKE_INFORMATION_AUTORUN, true).toBool();
m_autoCreateBuildDirectory = map.value(CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY, false).toBool();
//loading a CMakeTool from SDK is always autodetection //loading a CMakeTool from SDK is always autodetection
if (!fromSdk) if (!fromSdk)
@@ -102,6 +104,15 @@ void CMakeTool::setAutorun(bool autoRun)
CMakeToolManager::notifyAboutUpdate(this); CMakeToolManager::notifyAboutUpdate(this);
} }
void CMakeTool::setAutoCreateBuildDirectory(bool autoBuildDir)
{
if (m_autoCreateBuildDirectory == autoBuildDir)
return;
m_autoCreateBuildDirectory = autoBuildDir;
CMakeToolManager::notifyAboutUpdate(this);
}
bool CMakeTool::isValid() const bool CMakeTool::isValid() const
{ {
if (!m_id.isValid()) if (!m_id.isValid())
@@ -142,6 +153,7 @@ QVariantMap CMakeTool::toMap() const
data.insert(CMAKE_INFORMATION_ID, m_id.toSetting()); data.insert(CMAKE_INFORMATION_ID, m_id.toSetting());
data.insert(CMAKE_INFORMATION_COMMAND, m_executable.toString()); data.insert(CMAKE_INFORMATION_COMMAND, m_executable.toString());
data.insert(CMAKE_INFORMATION_AUTORUN, m_isAutoRun); data.insert(CMAKE_INFORMATION_AUTORUN, m_isAutoRun);
data.insert(CMAKE_INFORMATION_AUTO_CREATE_BUILD_DIRECTORY, m_autoCreateBuildDirectory);
data.insert(CMAKE_INFORMATION_AUTODETECTED, m_isAutoDetected); data.insert(CMAKE_INFORMATION_AUTODETECTED, m_isAutoDetected);
return data; return data;
} }
@@ -162,6 +174,11 @@ bool CMakeTool::isAutoRun() const
return m_isAutoRun; return m_isAutoRun;
} }
bool CMakeTool::autoCreateBuildDirectory() const
{
return m_autoCreateBuildDirectory;
}
QList<CMakeTool::Generator> CMakeTool::supportedGenerators() const QList<CMakeTool::Generator> CMakeTool::supportedGenerators() const
{ {
readInformation(QueryType::GENERATORS); readInformation(QueryType::GENERATORS);

View File

@@ -90,9 +90,11 @@ public:
void setCMakeExecutable(const Utils::FileName &executable); void setCMakeExecutable(const Utils::FileName &executable);
void setAutorun(bool autoRun); void setAutorun(bool autoRun);
void setAutoCreateBuildDirectory(bool autoBuildDir);
Utils::FileName cmakeExecutable() const; Utils::FileName cmakeExecutable() const;
bool isAutoRun() const; bool isAutoRun() const;
bool autoCreateBuildDirectory() const;
QList<Generator> supportedGenerators() const; QList<Generator> supportedGenerators() const;
TextEditor::Keywords keywords(); TextEditor::Keywords keywords();
bool hasServerMode() const; bool hasServerMode() const;
@@ -127,6 +129,7 @@ private:
bool m_isAutoRun = true; bool m_isAutoRun = true;
bool m_isAutoDetected = false; bool m_isAutoDetected = false;
bool m_autoCreateBuildDirectory = false;
mutable bool m_didAttemptToRun = false; mutable bool m_didAttemptToRun = false;
mutable bool m_didRun = false; mutable bool m_didRun = false;

View File

@@ -135,23 +135,23 @@ bool ConfigModel::hasCMakeChanges() const
return Utils::contains(m_configuration, [](const InternalDataItem &i) { return i.isCMakeChanged; }); return Utils::contains(m_configuration, [](const InternalDataItem &i) { return i.isCMakeChanged; });
} }
bool ConfigModel::canForceToString(const QModelIndex &idx) const bool ConfigModel::canForceTo(const QModelIndex &idx, const ConfigModel::DataItem::Type type) const
{ {
if (idx.model() != const_cast<ConfigModel *>(this) || idx.column() != 1) if (idx.model() != const_cast<ConfigModel *>(this) || idx.column() != 1)
return false; return false;
Utils::TreeItem *item = itemForIndex(idx); Utils::TreeItem *item = itemForIndex(idx);
auto cmti = dynamic_cast<Internal::ConfigModelTreeItem *>(item); auto cmti = dynamic_cast<Internal::ConfigModelTreeItem *>(item);
return cmti && (cmti->dataItem->type != DataItem::STRING); return cmti && (cmti->dataItem->type != type);
} }
void ConfigModel::forceToString(const QModelIndex &idx) void ConfigModel::forceTo(const QModelIndex &idx, const ConfigModel::DataItem::Type type)
{ {
QTC_ASSERT(canForceToString(idx), return); QTC_ASSERT(canForceTo(idx, type), return);
Utils::TreeItem *item = itemForIndex(idx); Utils::TreeItem *item = itemForIndex(idx);
auto cmti = dynamic_cast<Internal::ConfigModelTreeItem *>(item); auto cmti = dynamic_cast<Internal::ConfigModelTreeItem *>(item);
cmti->dataItem->type = DataItem::STRING; cmti->dataItem->type = type;
const QModelIndex valueIdx = idx.sibling(1, idx.column()); const QModelIndex valueIdx = idx.sibling(idx.row(), 1);
emit dataChanged(valueIdx, valueIdx); emit dataChanged(valueIdx, valueIdx);
} }

View File

@@ -73,8 +73,8 @@ public:
bool hasChanges() const; bool hasChanges() const;
bool hasCMakeChanges() const; bool hasCMakeChanges() const;
bool canForceToString(const QModelIndex &idx) const; bool canForceTo(const QModelIndex &idx, const DataItem::Type type) const;
void forceToString(const QModelIndex &idx); void forceTo(const QModelIndex &idx, const DataItem::Type type);
static DataItem dataItemFromIndex(const QModelIndex &idx); static DataItem dataItemFromIndex(const QModelIndex &idx);

View File

@@ -207,7 +207,7 @@ const char TR_CLEAR_MENU[] = QT_TRANSLATE_NOOP("Core", "Clear Menu");
const char DEFAULT_BUILD_DIRECTORY[] = "../%{JS: Util.asciify(\"build-%{CurrentProject:Name}-%{CurrentKit:FileSystemName}-%{CurrentBuild:Name}\")}"; const char DEFAULT_BUILD_DIRECTORY[] = "../%{JS: Util.asciify(\"build-%{CurrentProject:Name}-%{CurrentKit:FileSystemName}-%{CurrentBuild:Name}\")}";
const int TARGET_ICON_SIZE = 32; const int MODEBAR_ICON_SIZE = 34;
const int DEFAULT_MAX_LINE_COUNT = 100000; const int DEFAULT_MAX_LINE_COUNT = 100000;
} // namespace Constants } // namespace Constants

View File

@@ -178,7 +178,7 @@ void FancyToolButton::paintEvent(QPaintEvent *event)
const QIcon::Mode iconMode = isEnabled() ? ((isDown() || isChecked()) ? QIcon::Active : QIcon::Normal) const QIcon::Mode iconMode = isEnabled() ? ((isDown() || isChecked()) ? QIcon::Active : QIcon::Normal)
: QIcon::Disabled; : QIcon::Disabled;
QRect iconRect(0, 0, Constants::TARGET_ICON_SIZE, Constants::TARGET_ICON_SIZE); QRect iconRect(0, 0, Constants::MODEBAR_ICON_SIZE, Constants::MODEBAR_ICON_SIZE);
// draw popup texts // draw popup texts
if (isTitledAction) { if (isTitledAction) {
@@ -203,7 +203,7 @@ void FancyToolButton::paintEvent(QPaintEvent *event)
painter.setFont(normalFont); painter.setFont(normalFont);
QPoint textOffset = centerRect.center() - QPoint(iconRect.width()/2, iconRect.height()/2); QPoint textOffset = centerRect.center() - QPoint(iconRect.width()/2, iconRect.height()/2);
textOffset = textOffset - QPoint(0, lineHeight + 4); textOffset = textOffset - QPoint(0, lineHeight + 3);
QRectF r(0, textOffset.y(), rect().width(), lineHeight); QRectF r(0, textOffset.y(), rect().width(), lineHeight);
painter.setPen(creatorTheme()->color(isEnabled() painter.setPen(creatorTheme()->color(isEnabled()
? Theme::PanelTextColorLight ? Theme::PanelTextColorLight
@@ -218,8 +218,8 @@ void FancyToolButton::paintEvent(QPaintEvent *event)
// draw build configuration name // draw build configuration name
textOffset = iconRect.center() + QPoint(iconRect.width()/2, iconRect.height()/2); textOffset = iconRect.center() + QPoint(iconRect.width()/2, iconRect.height()/2);
QRectF buildConfigRect[2]; QRectF buildConfigRect[2];
buildConfigRect[0] = QRectF(0, textOffset.y() + 5, rect().width(), lineHeight); buildConfigRect[0] = QRectF(0, textOffset.y() + 4, rect().width(), lineHeight);
buildConfigRect[1] = QRectF(0, textOffset.y() + 5 + lineHeight, rect().width(), lineHeight); buildConfigRect[1] = QRectF(0, textOffset.y() + 4 + lineHeight, rect().width(), lineHeight);
painter.setFont(boldFont); painter.setFont(boldFont);
QVector<QString> splitBuildConfiguration(2); QVector<QString> splitBuildConfiguration(2);
const QString buildConfiguration = defaultAction()->property("subtitle").toString(); const QString buildConfiguration = defaultAction()->property("subtitle").toString();

View File

@@ -25,6 +25,7 @@
#include "fancytabwidget.h" #include "fancytabwidget.h"
#include "fancyactionbar.h" #include "fancyactionbar.h"
#include "coreconstants.h"
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
#include <utils/stylehelper.h> #include <utils/stylehelper.h>
@@ -324,7 +325,10 @@ void FancyTabBar::paintTab(QPainter *painter, int tabIndex) const
tabIconRect.adjust(0, 4, 0, -textHeight); tabIconRect.adjust(0, 4, 0, -textHeight);
const QIcon::Mode iconMode = enabled ? (selected ? QIcon::Active : QIcon::Normal) const QIcon::Mode iconMode = enabled ? (selected ? QIcon::Active : QIcon::Normal)
: QIcon::Disabled; : QIcon::Disabled;
StyleHelper::drawIconWithShadow(tab->icon, tabIconRect, painter, iconMode); QRect iconRect(0, 0, Core::Constants::MODEBAR_ICON_SIZE, Core::Constants::MODEBAR_ICON_SIZE);
iconRect.moveCenter(tabIconRect.center());
iconRect = iconRect.intersected(tabIconRect);
StyleHelper::drawIconWithShadow(tab->icon, iconRect, painter, iconMode);
} }
painter->setOpacity(1.0); //FIXME: was 0.7 before? painter->setOpacity(1.0); //FIXME: was 0.7 before?

View File

@@ -210,8 +210,6 @@ SearchResultWidget::SearchResultWidget(QWidget *parent) :
this, &SearchResultWidget::handleReplaceButton); this, &SearchResultWidget::handleReplaceButton);
connect(m_replaceButton, &QAbstractButton::clicked, connect(m_replaceButton, &QAbstractButton::clicked,
this, &SearchResultWidget::handleReplaceButton); this, &SearchResultWidget::handleReplaceButton);
connect(m_replaceTextEdit, &QLineEdit::textChanged,
this, &SearchResultWidget::handleReplaceEditTextChanged);
} }
SearchResultWidget::~SearchResultWidget() SearchResultWidget::~SearchResultWidget()
@@ -306,7 +304,6 @@ void SearchResultWidget::setSupportsReplace(bool replaceSupported, const QString
void SearchResultWidget::setTextToReplace(const QString &textToReplace) void SearchResultWidget::setTextToReplace(const QString &textToReplace)
{ {
m_replaceText = textToReplace;
m_replaceTextEdit->setText(textToReplace); m_replaceTextEdit->setText(textToReplace);
} }
@@ -409,6 +406,7 @@ void SearchResultWidget::goToPrevious()
void SearchResultWidget::restart() void SearchResultWidget::restart()
{ {
m_replaceTextEdit->setEnabled(false); m_replaceTextEdit->setEnabled(false);
m_replaceButton->setEnabled(false);
m_searchResultTreeView->clear(); m_searchResultTreeView->clear();
m_count = 0; m_count = 0;
Id sizeWarningId(SIZE_WARNING_ID); Id sizeWarningId(SIZE_WARNING_ID);
@@ -418,7 +416,6 @@ void SearchResultWidget::restart()
m_searchAgainButton->setVisible(false); m_searchAgainButton->setVisible(false);
m_messageWidget->setVisible(false); m_messageWidget->setVisible(false);
updateMatchesFoundLabel(); updateMatchesFoundLabel();
handleReplaceEditTextChanged();
emit restarted(); emit restarted();
} }
@@ -439,6 +436,7 @@ void SearchResultWidget::finishSearch(bool canceled)
m_infoBar.removeInfo(sizeWarningId); m_infoBar.removeInfo(sizeWarningId);
m_infoBar.enableInfo(sizeWarningId); m_infoBar.enableInfo(sizeWarningId);
m_replaceTextEdit->setEnabled(m_count > 0); m_replaceTextEdit->setEnabled(m_count > 0);
m_replaceButton->setEnabled(m_count > 0);
m_preserveCaseCheck->setEnabled(m_count > 0); m_preserveCaseCheck->setEnabled(m_count > 0);
m_cancelButton->setVisible(false); m_cancelButton->setVisible(false);
m_messageWidget->setVisible(canceled); m_messageWidget->setVisible(canceled);
@@ -463,15 +461,6 @@ void SearchResultWidget::cancelAfterSizeWarning()
emit paused(false); emit paused(false);
} }
void SearchResultWidget::handleReplaceEditTextChanged()
{
const bool enabled = m_replaceTextEdit->text() != m_replaceText;
m_replaceButton->setEnabled(enabled);
m_replaceButton->setToolTip(enabled
? QString()
: tr("Cannot replace because replacement text is unchanged."));
}
void SearchResultWidget::handleJumpToSearchResult(const SearchResultItem &item) void SearchResultWidget::handleJumpToSearchResult(const SearchResultItem &item)
{ {
emit activated(item); emit activated(item);

View File

@@ -115,7 +115,6 @@ private:
void setShowReplaceUI(bool visible); void setShowReplaceUI(bool visible);
void continueAfterSizeWarning(); void continueAfterSizeWarning();
void cancelAfterSizeWarning(); void cancelAfterSizeWarning();
void handleReplaceEditTextChanged();
QList<SearchResultItem> checkedItems() const; QList<SearchResultItem> checkedItems() const;
void updateMatchesFoundLabel(); void updateMatchesFoundLabel();
@@ -142,7 +141,6 @@ private:
bool m_isShowingReplaceUI = false; bool m_isShowingReplaceUI = false;
bool m_searchAgainSupported = false; bool m_searchAgainSupported = false;
bool m_replaceSupported = false; bool m_replaceSupported = false;
QString m_replaceText;
}; };
} // Internal } // Internal

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 426 B

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 B

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 B

After

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 B

After

Width:  |  Height:  |  Size: 117 B

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