Clang: Add clang query

Clang query is mechanism to use AST matcher to search for code. Think
about regular expression but in the context of AST. So you get a semantic
search tool for C++.

Change-Id: I72e882c5b53a0c52f352a3664847c4c3e4f6fc2e
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Tim Jenssen
2016-11-15 15:38:12 +01:00
parent 96187594b5
commit 9c7ff5199f
99 changed files with 4603 additions and 246 deletions

View File

@@ -57,7 +57,16 @@ SOURCES += $$PWD/clangcodemodelserverinterface.cpp \
$$PWD/sourcelocationcontainerv2.cpp \ $$PWD/sourcelocationcontainerv2.cpp \
$$PWD/sourcelocationsforrenamingmessage.cpp \ $$PWD/sourcelocationsforrenamingmessage.cpp \
$$PWD/requestsourcelocationforrenamingmessage.cpp \ $$PWD/requestsourcelocationforrenamingmessage.cpp \
$$PWD/filepath.cpp $$PWD/filepath.cpp \
$$PWD/sourcerangescontainer.cpp \
$$PWD/sourcerangecontainerv2.cpp \
$$PWD/dynamicastmatcherdiagnosticcontainer.cpp \
$$PWD/dynamicastmatcherdiagnosticcontextcontainer.cpp \
$$PWD/dynamicastmatcherdiagnosticmessagecontainer.cpp \
$$PWD/requestsourcerangesanddiagnosticsforquerymessage.cpp \
$$PWD/sourcerangesanddiagnosticsforquerymessage.cpp \
$$PWD/sourcerangewithtextcontainer.cpp \
$$PWD/filecontainerv2.cpp
HEADERS += \ HEADERS += \
$$PWD/clangcodemodelserverinterface.h \ $$PWD/clangcodemodelserverinterface.h \
@@ -110,6 +119,17 @@ HEADERS += \
$$PWD/sourcelocationcontainerv2.h \ $$PWD/sourcelocationcontainerv2.h \
$$PWD/sourcelocationsforrenamingmessage.h \ $$PWD/sourcelocationsforrenamingmessage.h \
$$PWD/requestsourcelocationforrenamingmessage.h \ $$PWD/requestsourcelocationforrenamingmessage.h \
$$PWD/filepath.h $$PWD/filepath.h \
$$PWD/sourcerangescontainer.h \
$$PWD/sourcefilepathcontainerbase.h \
$$PWD/sourcerangecontainerv2.h \
$$PWD/dynamicmatcherdiagnostics.h \
$$PWD/dynamicastmatcherdiagnosticcontainer.h \
$$PWD/dynamicastmatcherdiagnosticcontextcontainer.h \
$$PWD/dynamicastmatcherdiagnosticmessagecontainer.h \
$$PWD/requestsourcerangesanddiagnosticsforquerymessage.h \
$$PWD/sourcerangesanddiagnosticsforquerymessage.h \
$$PWD/sourcerangewithtextcontainer.h \
$$PWD/filecontainerv2.h
contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols

View File

@@ -29,6 +29,10 @@
#include <QtCore/qglobal.h> #include <QtCore/qglobal.h>
#ifdef UNIT_TESTS
#include <gtest/gtest.h>
#endif
#if defined(CLANGBACKENDIPC_BUILD_LIB) #if defined(CLANGBACKENDIPC_BUILD_LIB)
# define CMBIPC_EXPORT Q_DECL_EXPORT # define CMBIPC_EXPORT Q_DECL_EXPORT
#elif defined(CLANGBACKENDIPC_BUILD_STATIC_LIB) #elif defined(CLANGBACKENDIPC_BUILD_STATIC_LIB)
@@ -41,6 +45,12 @@
# define CLANGBACKENDPROCESSPATH "" # define CLANGBACKENDPROCESSPATH ""
#endif #endif
namespace Utils {
template<uint Size>
class BasicSmallString;
using SmallString = BasicSmallString<31>;
}
namespace ClangBackEnd { namespace ClangBackEnd {
enum class DiagnosticSeverity : quint32 // one to one mapping of the clang enum numbers enum class DiagnosticSeverity : quint32 // one to one mapping of the clang enum numbers
@@ -109,7 +119,10 @@ enum class MessageType : quint8 {
ProjectPartsDoNotExistMessage, ProjectPartsDoNotExistMessage,
SourceLocationsForRenamingMessage, SourceLocationsForRenamingMessage,
RequestSourceLocationsForRenamingMessage RequestSourceLocationsForRenamingMessage,
RequestSourceRangesAndDiagnosticsForQueryMessage,
SourceRangesAndDiagnosticsForQueryMessage
}; };
template<MessageType messageEnumeration> template<MessageType messageEnumeration>

View File

@@ -0,0 +1,59 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "dynamicastmatcherdiagnosticcontainer.h"
namespace ClangBackEnd {
QDebug operator<<(QDebug debug, const DynamicASTMatcherDiagnosticContainer &container)
{
debug.nospace() << "DynamicASTMatcherDiagnosticContextContainer("
<< container.messages() << ", "
<< container.contexts()
<< ")";
return debug;
}
void PrintTo(const DynamicASTMatcherDiagnosticContainer &container, ::std::ostream* os)
{
*os << "{[";
for (const auto &message : container.messages()) {
PrintTo(message, os);
*os << ", ";
}
*os << "], [";
for (const auto &context : container.contexts()) {
PrintTo(context, os);
*os << ", ";
}
*os << "]}";
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,103 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "dynamicastmatcherdiagnosticmessagecontainer.h"
#include "dynamicastmatcherdiagnosticcontextcontainer.h"
namespace ClangBackEnd {
class DynamicASTMatcherDiagnosticContainer
{
public:
DynamicASTMatcherDiagnosticContainer() = default;
DynamicASTMatcherDiagnosticContainer(std::vector<DynamicASTMatcherDiagnosticMessageContainer> &&messages,
std::vector<DynamicASTMatcherDiagnosticContextContainer> &&contexts)
: messages_(std::move(messages)),
contexts_(std::move(contexts))
{
}
const std::vector<DynamicASTMatcherDiagnosticMessageContainer> &messages() const
{
return messages_;
}
const std::vector<DynamicASTMatcherDiagnosticContextContainer> &contexts() const
{
return contexts_;
}
void insertMessage(V2::SourceRangeContainer &&sourceRange,
ClangQueryDiagnosticErrorType errorType,
Utils::SmallStringVector &&arguments) {
messages_.emplace_back(std::move(sourceRange), errorType, std::move(arguments));
}
void insertContext(V2::SourceRangeContainer &&sourceRange,
ClangQueryDiagnosticContextType contextType,
Utils::SmallStringVector &&arguments) {
contexts_.emplace_back(std::move(sourceRange), contextType, std::move(arguments));
}
friend QDataStream &operator<<(QDataStream &out, const DynamicASTMatcherDiagnosticContainer &container)
{
out << container.messages_;
out << container.contexts_;
return out;
}
friend QDataStream &operator>>(QDataStream &in, DynamicASTMatcherDiagnosticContainer &container)
{
in >> container.messages_;
in >> container.contexts_;
return in;
}
friend bool operator==(const DynamicASTMatcherDiagnosticContainer &first,
const DynamicASTMatcherDiagnosticContainer &second)
{
return first.messages_ == second.messages_
&& first.contexts_ == second.contexts_;
}
DynamicASTMatcherDiagnosticContainer clone() const
{
return DynamicASTMatcherDiagnosticContainer(Utils::clone(messages_),
Utils::clone(contexts_));
}
private:
std::vector<DynamicASTMatcherDiagnosticMessageContainer> messages_;
std::vector<DynamicASTMatcherDiagnosticContextContainer> contexts_;
};
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const DynamicASTMatcherDiagnosticContainer &container);
void PrintTo(const DynamicASTMatcherDiagnosticContainer &container, ::std::ostream* os);
} // namespace ClangBackEnd

View File

@@ -0,0 +1,73 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "dynamicastmatcherdiagnosticcontextcontainer.h"
namespace ClangBackEnd {
QDebug operator<<(QDebug debug, const DynamicASTMatcherDiagnosticContextContainer &container)
{
debug.nospace() << "DynamicASTMatcherDiagnosticContextContainer("
<< container.sourceRange() << ", "
<< container.contextTypeText() << ", "
<< container.arguments()
<< ")";
return debug;
}
void PrintTo(const DynamicASTMatcherDiagnosticContextContainer &container, ::std::ostream* os)
{
*os << "{"
<< container.contextTypeText() << ": ";
PrintTo(container.sourceRange(), os);
*os << ", [";
for (const auto &argument : container.arguments()) {
PrintTo(argument, os);
*os << ", ";
}
*os << "]}";
}
#define RETURN_CASE(name) \
case ClangQueryDiagnosticContextType::name: return #name;
Utils::SmallString DynamicASTMatcherDiagnosticContextContainer::contextTypeText() const
{
switch (contextType_) {
RETURN_CASE(MatcherArg)
RETURN_CASE(MatcherConstruct)
}
Q_UNREACHABLE();
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,111 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "dynamicmatcherdiagnostics.h"
#include "sourcerangecontainerv2.h"
#include <utils/smallstringio.h>
namespace ClangBackEnd {
class DynamicASTMatcherDiagnosticContextContainer
{
public:
DynamicASTMatcherDiagnosticContextContainer() = default;
DynamicASTMatcherDiagnosticContextContainer(V2::SourceRangeContainer &&sourceRange,
ClangQueryDiagnosticContextType contextType,
Utils::SmallStringVector &&arguments)
: sourceRange_(sourceRange),
contextType_(contextType),
arguments_(std::move(arguments))
{
}
const V2::SourceRangeContainer &sourceRange() const
{
return sourceRange_;
}
ClangQueryDiagnosticContextType contextType() const
{
return contextType_;
}
Utils::SmallString contextTypeText() const;
const Utils::SmallStringVector &arguments() const
{
return arguments_;
}
friend QDataStream &operator<<(QDataStream &out, const DynamicASTMatcherDiagnosticContextContainer &container)
{
out << container.sourceRange_;
out << quint32(container.contextType_);
out << container.arguments_;
return out;
}
friend QDataStream &operator>>(QDataStream &in, DynamicASTMatcherDiagnosticContextContainer &container)
{
quint32 contextType;
in >> container.sourceRange_;
in >> contextType;
in >> container.arguments_;
container.contextType_ = static_cast<ClangQueryDiagnosticContextType>(contextType);
return in;
}
friend bool operator==(const DynamicASTMatcherDiagnosticContextContainer &first,
const DynamicASTMatcherDiagnosticContextContainer &second)
{
return first.contextType_ == second.contextType_
&& first.sourceRange_ == second.sourceRange_
&& first.arguments_ == second.arguments_;
}
DynamicASTMatcherDiagnosticContextContainer clone() const
{
return DynamicASTMatcherDiagnosticContextContainer(sourceRange_.clone(),
contextType_,
arguments_.clone());
}
private:
V2::SourceRangeContainer sourceRange_;
ClangQueryDiagnosticContextType contextType_;
Utils::SmallStringVector arguments_;
};
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const DynamicASTMatcherDiagnosticContextContainer &container);
void PrintTo(const DynamicASTMatcherDiagnosticContextContainer &container, ::std::ostream* os);
} // namespace ClangBackEnd

View File

@@ -0,0 +1,87 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "dynamicastmatcherdiagnosticmessagecontainer.h"
#define RETURN_CASE(name) \
case ClangQueryDiagnosticErrorType::name: return #name;
namespace ClangBackEnd {
QDebug operator<<(QDebug debug, const DynamicASTMatcherDiagnosticMessageContainer &container)
{
debug.nospace() << "DynamicASTMatcherDiagnosticMessageContainer("
<< container.sourceRange() << ", "
<< container.errorTypeText() << ", "
<< container.arguments()
<< ")";
return debug;
}
void PrintTo(const DynamicASTMatcherDiagnosticMessageContainer &container, ::std::ostream* os)
{
*os << "{"
<< container.errorTypeText() << ": ";
PrintTo(container.sourceRange(), os);
*os << ", [";
for (const auto &argument : container.arguments()) {
PrintTo(argument, os);
*os << ", ";
}
*os << "]}";
}
Utils::SmallString DynamicASTMatcherDiagnosticMessageContainer::errorTypeText() const
{
switch (errorType_) {
RETURN_CASE(None)
RETURN_CASE(RegistryMatcherNotFound)
RETURN_CASE(RegistryWrongArgCount)
RETURN_CASE(RegistryWrongArgType)
RETURN_CASE(RegistryNotBindable)
RETURN_CASE(RegistryAmbiguousOverload)
RETURN_CASE(RegistryValueNotFound)
RETURN_CASE(ParserStringError)
RETURN_CASE(ParserNoOpenParen)
RETURN_CASE(ParserNoCloseParen)
RETURN_CASE(ParserNoComma)
RETURN_CASE(ParserNoCode)
RETURN_CASE(ParserNotAMatcher)
RETURN_CASE(ParserInvalidToken)
RETURN_CASE(ParserMalformedBindExpr)
RETURN_CASE(ParserTrailingCode)
RETURN_CASE(ParserUnsignedError)
RETURN_CASE(ParserOverloadedType)
}
Q_UNREACHABLE();
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,111 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "dynamicmatcherdiagnostics.h"
#include "sourcerangecontainerv2.h"
#include <utils/smallstringio.h>
namespace ClangBackEnd {
class DynamicASTMatcherDiagnosticMessageContainer
{
public:
DynamicASTMatcherDiagnosticMessageContainer() = default;
DynamicASTMatcherDiagnosticMessageContainer(V2::SourceRangeContainer &&sourceRange,
ClangQueryDiagnosticErrorType errorType,
Utils::SmallStringVector &&arguments)
: sourceRange_(sourceRange),
errorType_(errorType),
arguments_(std::move(arguments))
{
}
const V2::SourceRangeContainer &sourceRange() const
{
return sourceRange_;
}
ClangQueryDiagnosticErrorType errorType() const
{
return errorType_;
}
Utils::SmallString errorTypeText() const;
const Utils::SmallStringVector &arguments() const
{
return arguments_;
}
friend QDataStream &operator<<(QDataStream &out, const DynamicASTMatcherDiagnosticMessageContainer &container)
{
out << container.sourceRange_;
out << quint32(container.errorType_);
out << container.arguments_;
return out;
}
friend QDataStream &operator>>(QDataStream &in, DynamicASTMatcherDiagnosticMessageContainer &container)
{
quint32 errorType;
in >> container.sourceRange_;
in >> errorType;
in >> container.arguments_;
container.errorType_ = static_cast<ClangQueryDiagnosticErrorType>(errorType);
return in;
}
friend bool operator==(const DynamicASTMatcherDiagnosticMessageContainer &first,
const DynamicASTMatcherDiagnosticMessageContainer &second)
{
return first.errorType_ == second.errorType_
&& first.sourceRange_ == second.sourceRange_
&& first.arguments_ == second.arguments_;
}
DynamicASTMatcherDiagnosticMessageContainer clone() const
{
return DynamicASTMatcherDiagnosticMessageContainer(sourceRange_.clone(),
errorType_,
arguments_.clone());
}
private:
V2::SourceRangeContainer sourceRange_;
ClangQueryDiagnosticErrorType errorType_;
Utils::SmallStringVector arguments_;
};
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const DynamicASTMatcherDiagnosticMessageContainer &container);
void PrintTo(const DynamicASTMatcherDiagnosticMessageContainer &container, ::std::ostream* os);
} // namespace ClangBackEnd

View File

@@ -0,0 +1,58 @@
/****************************************************************************
**
** Copyright (C) 2016 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
namespace ClangBackEnd {
enum class ClangQueryDiagnosticContextType {
MatcherArg,
MatcherConstruct
};
enum class ClangQueryDiagnosticErrorType {
None,
RegistryMatcherNotFound,
RegistryWrongArgCount,
RegistryWrongArgType,
RegistryNotBindable,
RegistryAmbiguousOverload,
RegistryValueNotFound,
ParserStringError,
ParserNoOpenParen,
ParserNoCloseParen,
ParserNoComma,
ParserNoCode,
ParserNotAMatcher,
ParserInvalidToken,
ParserMalformedBindExpr,
ParserTrailingCode,
ParserUnsignedError,
ParserOverloadedType
};
} // namespace ClangBackEnd

View File

@@ -0,0 +1,58 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "filecontainerv2.h"
namespace ClangBackEnd {
namespace V2 {
QDebug operator<<(QDebug debug, const FileContainer &container)
{
debug.nospace() << "FileContainer("
<< container.filePath() << ", "
<< container.commandLineArguments() << ", "
<< container.documentRevision();
debug.nospace() << ")";
return debug;
}
void PrintTo(const FileContainer &container, ::std::ostream* os)
{
*os << "("
<< container.filePath() << ", "
<< container.commandLineArguments() << ", "
<< container.documentRevision();
if (container.unsavedFileContent().hasContent())
*os << ", \""
<< container.unsavedFileContent();
*os << "\")";
}
} // namespace V2
} // namespace ClangBackEnd

View File

@@ -0,0 +1,127 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "clangbackendipc_global.h"
#include "filepath.h"
namespace ClangBackEnd {
namespace V2 {
class FileContainer
{
public:
FileContainer() = default;
FileContainer(FilePath &&filePath,
Utils::SmallString &&unsavedFileContent,
Utils::SmallStringVector &&commandLineArguments,
quint32 documentRevision = 0)
: filePath_(std::move(filePath)),
unsavedFileContent_(std::move(unsavedFileContent)),
commandLineArguments_(std::move(commandLineArguments)),
documentRevision_(documentRevision)
{
}
const FilePath &filePath() const
{
return filePath_;
}
const Utils::SmallStringVector &commandLineArguments() const
{
return commandLineArguments_;
}
Utils::SmallStringVector takeCommandLineArguments()
{
return std::move(commandLineArguments_);
}
const Utils::SmallString &unsavedFileContent() const
{
return unsavedFileContent_;
}
Utils::SmallString takeUnsavedFileContent()
{
return std::move(unsavedFileContent_);
}
quint32 documentRevision() const
{
return documentRevision_;
}
friend QDataStream &operator<<(QDataStream &out, const FileContainer &container)
{
out << container.filePath_;
out << container.commandLineArguments_;
out << container.unsavedFileContent_;
out << container.documentRevision_;
return out;
}
friend QDataStream &operator>>(QDataStream &in, FileContainer &container)
{
in >> container.filePath_;
in >> container.commandLineArguments_;
in >> container.unsavedFileContent_;
in >> container.documentRevision_;
return in;
}
friend bool operator==(const FileContainer &first, const FileContainer &second)
{
return first.filePath_ == second.filePath_
&& first.commandLineArguments_ == second.commandLineArguments_;
}
FileContainer clone() const
{
return FileContainer(filePath_.clone(),
unsavedFileContent_.clone(),
commandLineArguments_.clone(),
documentRevision_);
}
private:
FilePath filePath_;
Utils::SmallString unsavedFileContent_;
Utils::SmallStringVector commandLineArguments_;
quint32 documentRevision_ = 0;
};
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const FileContainer &container);
void PrintTo(const FileContainer &container, ::std::ostream* os);
} // namespace V2
} // namespace ClangBackEnd

View File

@@ -27,15 +27,31 @@
#include "clangbackendipc_global.h" #include "clangbackendipc_global.h"
#include <utils/smallstring.h>
#include <utils/smallstringio.h> #include <utils/smallstringio.h>
#include <QDataStream>
namespace ClangBackEnd { namespace ClangBackEnd {
struct FilePath class FilePath
{ {
public: public:
FilePath() = default; FilePath() = default;
explicit FilePath(const QString &filePath)
{
Utils::SmallString utf8FilePath = filePath;
auto foundReverse = std::find(utf8FilePath.rbegin(), utf8FilePath.rend(), '/');
auto found = foundReverse.base();
Utils::SmallString fileName(found, utf8FilePath.end());
if (foundReverse != utf8FilePath.rend())
utf8FilePath.resize(std::size_t(std::distance(utf8FilePath.begin(), --found)));
directory_ = std::move(utf8FilePath);
name_ = std::move(fileName);
}
FilePath(Utils::SmallString &&directory, Utils::SmallString &&name) FilePath(Utils::SmallString &&directory, Utils::SmallString &&name)
: directory_(std::move(directory)), : directory_(std::move(directory)),
name_(std::move(name)) name_(std::move(name))
@@ -46,11 +62,21 @@ public:
return directory_; return directory_;
} }
Utils::SmallString takeDirectory()
{
return std::move(directory_);
}
const Utils::SmallString &name() const const Utils::SmallString &name() const
{ {
return name_; return name_;
} }
Utils::SmallString takeName()
{
return std::move(name_);
}
friend QDataStream &operator<<(QDataStream &out, const FilePath &filePath) friend QDataStream &operator<<(QDataStream &out, const FilePath &filePath)
{ {
out << filePath.directory_; out << filePath.directory_;
@@ -67,6 +93,13 @@ public:
return in; return in;
} }
friend std::ostream &operator<<(std::ostream &out, const FilePath &filePath)
{
out << filePath.directory() << "/" << filePath.name();
return out;
}
friend bool operator==(const FilePath &first, const FilePath &second) friend bool operator==(const FilePath &first, const FilePath &second)
{ {
return first.directory_ == second.directory_ return first.directory_ == second.directory_

View File

@@ -27,6 +27,7 @@
#include "messageenvelop.h" #include "messageenvelop.h"
#include "sourcelocationsforrenamingmessage.h" #include "sourcelocationsforrenamingmessage.h"
#include "sourcerangesanddiagnosticsforquerymessage.h"
#include <QDebug> #include <QDebug>
@@ -41,6 +42,9 @@ void RefactoringClientInterface::dispatch(const MessageEnvelop &messageEnvelop)
case MessageType::SourceLocationsForRenamingMessage: case MessageType::SourceLocationsForRenamingMessage:
sourceLocationsForRenamingMessage(messageEnvelop.message<SourceLocationsForRenamingMessage>()); sourceLocationsForRenamingMessage(messageEnvelop.message<SourceLocationsForRenamingMessage>());
break; break;
case MessageType::SourceRangesAndDiagnosticsForQueryMessage:
sourceRangesAndDiagnosticsForQueryMessage(messageEnvelop.message<SourceRangesAndDiagnosticsForQueryMessage>());
break;
default: default:
qWarning() << "Unknown IpcClientMessage"; qWarning() << "Unknown IpcClientMessage";
} }

View File

@@ -32,6 +32,7 @@
namespace ClangBackEnd { namespace ClangBackEnd {
class SourceLocationsForRenamingMessage; class SourceLocationsForRenamingMessage;
class SourceRangesAndDiagnosticsForQueryMessage;
class SourceLocationsContainer; class SourceLocationsContainer;
class CMBIPC_EXPORT RefactoringClientInterface : public IpcClientInterface class CMBIPC_EXPORT RefactoringClientInterface : public IpcClientInterface
@@ -45,6 +46,7 @@ public:
virtual void alive() = 0; virtual void alive() = 0;
virtual void sourceLocationsForRenamingMessage(SourceLocationsForRenamingMessage &&message) = 0; virtual void sourceLocationsForRenamingMessage(SourceLocationsForRenamingMessage &&message) = 0;
virtual void sourceRangesAndDiagnosticsForQueryMessage(SourceRangesAndDiagnosticsForQueryMessage &&message) = 0;
virtual void setLocalRenamingCallback(RenameCallback &&localRenamingCallback) = 0; virtual void setLocalRenamingCallback(RenameCallback &&localRenamingCallback) = 0;
}; };

View File

@@ -29,6 +29,7 @@
#include "messageenvelop.h" #include "messageenvelop.h"
#include "refactoringserverinterface.h" #include "refactoringserverinterface.h"
#include "sourcelocationsforrenamingmessage.h" #include "sourcelocationsforrenamingmessage.h"
#include "sourcerangesanddiagnosticsforquerymessage.h"
#include <QDebug> #include <QDebug>
#include <QIODevice> #include <QIODevice>
@@ -79,4 +80,9 @@ void RefactoringClientProxy::sourceLocationsForRenamingMessage(SourceLocationsFo
writeMessageBlock.write(message); writeMessageBlock.write(message);
} }
void RefactoringClientProxy::sourceRangesAndDiagnosticsForQueryMessage(SourceRangesAndDiagnosticsForQueryMessage &&message)
{
writeMessageBlock.write(message);
}
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -50,6 +50,7 @@ public:
void alive() override; void alive() override;
void sourceLocationsForRenamingMessage(SourceLocationsForRenamingMessage &&message) override; void sourceLocationsForRenamingMessage(SourceLocationsForRenamingMessage &&message) override;
void sourceRangesAndDiagnosticsForQueryMessage(SourceRangesAndDiagnosticsForQueryMessage &&message);
void setLocalRenamingCallback(RenameCallback &&) final {} void setLocalRenamingCallback(RenameCallback &&) final {}

View File

@@ -27,6 +27,7 @@
#include "messageenvelop.h" #include "messageenvelop.h"
#include "requestsourcelocationforrenamingmessage.h" #include "requestsourcelocationforrenamingmessage.h"
#include "requestsourcerangesanddiagnosticsforquerymessage.h"
#include <QDebug> #include <QDebug>
@@ -41,6 +42,9 @@ void RefactoringServerInterface::dispatch(const MessageEnvelop &messageEnvelop)
case MessageType::RequestSourceLocationsForRenamingMessage: case MessageType::RequestSourceLocationsForRenamingMessage:
requestSourceLocationsForRenamingMessage(messageEnvelop.message<RequestSourceLocationsForRenamingMessage>()); requestSourceLocationsForRenamingMessage(messageEnvelop.message<RequestSourceLocationsForRenamingMessage>());
break; break;
case MessageType::RequestSourceRangesAndDiagnosticsForQueryMessage:
requestSourceRangesAndDiagnosticsForQueryMessage(messageEnvelop.message<RequestSourceRangesAndDiagnosticsForQueryMessage>());
break;
default: default:
qWarning() << "Unknown IpcClientMessage"; qWarning() << "Unknown IpcClientMessage";
} }

View File

@@ -33,6 +33,7 @@ namespace ClangBackEnd {
class RefactoringClientInterface; class RefactoringClientInterface;
class RequestSourceLocationsForRenamingMessage; class RequestSourceLocationsForRenamingMessage;
class RequestSourceRangesAndDiagnosticsForQueryMessage;
class CMBIPC_EXPORT RefactoringServerInterface : public IpcServerInterface<RefactoringClientInterface> class CMBIPC_EXPORT RefactoringServerInterface : public IpcServerInterface<RefactoringClientInterface>
{ {
@@ -41,6 +42,19 @@ public:
virtual void end() = 0; virtual void end() = 0;
virtual void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) = 0; virtual void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) = 0;
virtual void requestSourceRangesAndDiagnosticsForQueryMessage(RequestSourceRangesAndDiagnosticsForQueryMessage &&message) = 0;
bool isUsable() const
{
return isUsable_;
}
void setUsable(bool isUsable)
{
isUsable_ = isUsable;
}
private:
bool isUsable_ = false;
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -29,6 +29,7 @@
#include "messageenvelop.h" #include "messageenvelop.h"
#include "refactoringclientinterface.h" #include "refactoringclientinterface.h"
#include "requestsourcelocationforrenamingmessage.h" #include "requestsourcelocationforrenamingmessage.h"
#include "requestsourcerangesanddiagnosticsforquerymessage.h"
#include <QIODevice> #include <QIODevice>
#include <QVector> #include <QVector>
@@ -50,7 +51,12 @@ void RefactoringServerProxy::end()
void RefactoringServerProxy::requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) void RefactoringServerProxy::requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message)
{ {
writeMessageBlock.write(message); writeMessageBlock.write(message);
}
void RefactoringServerProxy::requestSourceRangesAndDiagnosticsForQueryMessage(RequestSourceRangesAndDiagnosticsForQueryMessage &&message)
{
writeMessageBlock.write(message);
} }
void RefactoringServerProxy::readMessages() void RefactoringServerProxy::readMessages()

View File

@@ -51,6 +51,7 @@ public:
void end() override; void end() override;
void requestSourceLocationsForRenamingMessage(ClangBackEnd::RequestSourceLocationsForRenamingMessage &&message) override; void requestSourceLocationsForRenamingMessage(ClangBackEnd::RequestSourceLocationsForRenamingMessage &&message) override;
void requestSourceRangesAndDiagnosticsForQueryMessage(RequestSourceRangesAndDiagnosticsForQueryMessage &&message);
void readMessages(); void readMessages();

View File

@@ -40,15 +40,17 @@ QDebug operator<<(QDebug debug, const RequestSourceLocationsForRenamingMessage &
void PrintTo(const RequestSourceLocationsForRenamingMessage &message, ::std::ostream* os) void PrintTo(const RequestSourceLocationsForRenamingMessage &message, ::std::ostream* os)
{ {
*os << "RequestSourceLocationsForRenamingMessage("; Q_UNUSED(message)
PrintTo(message.filePath(), os); Q_UNUSED(os)
*os << ", " #ifdef UNIT_TESTS
*os << "RequestSourceLocationsForRenamingMessage("
<< ::testing::PrintToString(message.filePath()) << ", ("
<< message.line() << ", " << message.line() << ", "
<< message.column() << ", "; << message.column() << "), "
PrintTo(message.unsavedContent(), os); << message.unsavedContent() << ", "
*os << ", "; << message.commandLine()
PrintTo(message.commandLine(), os); << ")";
*os << ")"; #endif
} }
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -0,0 +1,51 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "requestsourcerangesanddiagnosticsforquerymessage.h"
namespace ClangBackEnd {
QDebug operator<<(QDebug debug, const RequestSourceRangesAndDiagnosticsForQueryMessage &message)
{
debug.nospace() << "RequestSourceRangesAndDiagnosticsForQuery("
<< message.query() << ", "
<< message.fileContainers() << ")";
return debug;
}
void PrintTo(const RequestSourceRangesAndDiagnosticsForQueryMessage &message, ::std::ostream* os)
{
Q_UNUSED(message)
Q_UNUSED(os)
#ifdef UNIT_TESTS
*os << "RequestSourceRangesAndDiagnosticsForQuery("
<< message.query() << ", "
<< message.fileContainers()
<< ")";
#endif
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,104 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "clangbackendipc_global.h"
#include "filecontainerv2.h"
namespace ClangBackEnd {
class CMBIPC_EXPORT RequestSourceRangesAndDiagnosticsForQueryMessage
{
public:
RequestSourceRangesAndDiagnosticsForQueryMessage() = default;
RequestSourceRangesAndDiagnosticsForQueryMessage(Utils::SmallString &&query,
std::vector<V2::FileContainer> &&fileContainers)
: query_(std::move(query)),
fileContainers_(std::move(fileContainers))
{}
const std::vector<V2::FileContainer> &fileContainers() const
{
return fileContainers_;
}
std::vector<V2::FileContainer> takeFileContainers()
{
return std::move(fileContainers_);
}
const Utils::SmallString &query() const
{
return query_;
}
Utils::SmallString takeQuery()
{
return std::move(query_);
}
friend QDataStream &operator<<(QDataStream &out, const RequestSourceRangesAndDiagnosticsForQueryMessage &message)
{
out << message.query_;
out << message.fileContainers_;
return out;
}
friend QDataStream &operator>>(QDataStream &in, RequestSourceRangesAndDiagnosticsForQueryMessage &message)
{
in >> message.query_;
in >> message.fileContainers_;
return in;
}
friend bool operator==(const RequestSourceRangesAndDiagnosticsForQueryMessage &first,
const RequestSourceRangesAndDiagnosticsForQueryMessage &second)
{
return first.query_ == second.query_
&& first.fileContainers_ == second.fileContainers_;
}
RequestSourceRangesAndDiagnosticsForQueryMessage clone() const
{
return RequestSourceRangesAndDiagnosticsForQueryMessage(query_.clone(),
Utils::clone(fileContainers_));
}
private:
Utils::SmallString query_;
std::vector<V2::FileContainer> fileContainers_;
};
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const RequestSourceRangesAndDiagnosticsForQueryMessage &message);
void PrintTo(const RequestSourceRangesAndDiagnosticsForQueryMessage &message, ::std::ostream* os);
DECLARE_MESSAGE(RequestSourceRangesAndDiagnosticsForQueryMessage)
} // namespace ClangBackEnd

View File

@@ -0,0 +1,66 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "filepath.h"
#include <unordered_map>
namespace ClangBackEnd {
using FilePathDict = std::unordered_map<uint, FilePath>;
class SourceFilePathContainerBase
{
public:
SourceFilePathContainerBase() = default;
SourceFilePathContainerBase(std::unordered_map<uint, FilePath> &&filePathHash)
: filePathHash(std::move(filePathHash))
{
}
void insertFilePath(uint fileId, Utils::SmallString &&fileDirectory, Utils::SmallString &&fileName)
{
filePathHash.emplace(std::piecewise_construct,
std::forward_as_tuple(fileId),
std::forward_as_tuple(std::move(fileDirectory), std::move(fileName)));
}
void reserve(std::size_t size)
{
filePathHash.reserve(size / 3);
}
const FilePathDict &filePaths() const
{
return filePathHash;
}
protected:
FilePathDict filePathHash;
};
} // namespace ClangBackEnd

View File

@@ -35,20 +35,22 @@ namespace V2 {
QDebug operator<<(QDebug debug, const SourceLocationContainer &container) QDebug operator<<(QDebug debug, const SourceLocationContainer &container)
{ {
debug.nospace() << "SourceLocationContainer(" debug.nospace() << "SourceLocationContainer("
<< container.fileHash() << ", "
<< container.line() << ", " << container.line() << ", "
<< container.column() << container.column() << ", "
<< container.offset() << ", "
<< container.fileHash()
<< ")"; << ")";
return debug; return debug;
} }
void PrintTo(const SourceLocationContainer &container, ::std::ostream* os) void PrintTo(const SourceLocationContainer &container, ::std::ostream* os)
{ {
*os << "[" *os << "("
<< container.fileHash() << ", "
<< container.line() << ", " << container.line() << ", "
<< container.column() << container.column() << ", "
<< "]"; << container.offset() << ", "
<< container.fileHash()
<< ")";
} }
} // namespace V2 } // namespace V2

View File

@@ -39,10 +39,12 @@ public:
SourceLocationContainer() = default; SourceLocationContainer() = default;
SourceLocationContainer(uint fileHash, SourceLocationContainer(uint fileHash,
uint line, uint line,
uint column) uint column,
uint offset)
: fileHash_(fileHash), : fileHash_(fileHash),
line_(line), line_(line),
column_(column) column_(column),
offset_(offset)
{ {
} }
@@ -61,11 +63,17 @@ public:
return column_; return column_;
} }
uint offset() const
{
return offset_;
}
friend QDataStream &operator<<(QDataStream &out, const SourceLocationContainer &container) friend QDataStream &operator<<(QDataStream &out, const SourceLocationContainer &container)
{ {
out << container.fileHash_; out << container.fileHash_;
out << container.line_; out << container.line_;
out << container.column_; out << container.column_;
out << container.offset_;
return out; return out;
} }
@@ -75,6 +83,7 @@ public:
in >> container.fileHash_; in >> container.fileHash_;
in >> container.line_; in >> container.line_;
in >> container.column_; in >> container.column_;
in >> container.offset_;
return in; return in;
} }
@@ -88,18 +97,20 @@ public:
{ {
return first.line_ != second.line_ return first.line_ != second.line_
|| first.column_ != second.column_ || first.column_ != second.column_
|| first.fileHash_ != second.fileHash_; || first.fileHash_ != second.fileHash_
|| first.offset_ != second.offset_;
} }
SourceLocationContainer clone() const SourceLocationContainer clone() const
{ {
return SourceLocationContainer(fileHash_, line_, column_); return SourceLocationContainer(fileHash_, line_, column_, offset_);
} }
private: private:
uint fileHash_ = 0; uint fileHash_ = 0;
uint line_ = 1; uint line_ = 1;
uint column_ = 1; uint column_ = 1;
uint offset_ = 0;
}; };
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const SourceLocationContainer &container); CMBIPC_EXPORT QDebug operator<<(QDebug debug, const SourceLocationContainer &container);

View File

@@ -46,12 +46,12 @@ QDebug operator<<(QDebug debug, const SourceLocationsContainer &container)
void PrintTo(const SourceLocationsContainer &container, ::std::ostream* os) void PrintTo(const SourceLocationsContainer &container, ::std::ostream* os)
{ {
*os << "SourceLocationsContainer("; *os << "(";
for (const auto &sourceLocation: container.sourceLocationContainers()) { for (const auto &sourceLocation: container.sourceLocationContainers()) {
*os << "[" *os << "("
<< container.filePathForSourceLocation(sourceLocation).name() << "," << container.filePathForSourceLocation(sourceLocation).name() << ","
<< sourceLocation.line() << "," << sourceLocation.line() << ","
<< sourceLocation.column() << "], "; << sourceLocation.column() << "), ";
} }
*os << ")"; *os << ")";
} }

View File

@@ -25,22 +25,20 @@
#pragma once #pragma once
#include "filepath.h" #include "sourcefilepathcontainerbase.h"
#include "sourcelocationcontainerv2.h" #include "sourcelocationcontainerv2.h"
#include <utils/smallstringvector.h> #include <utils/smallstringvector.h>
#include <unordered_map>
namespace ClangBackEnd { namespace ClangBackEnd {
class SourceLocationsContainer class SourceLocationsContainer : public SourceFilePathContainerBase
{ {
public: public:
SourceLocationsContainer() = default; SourceLocationsContainer() = default;
SourceLocationsContainer(std::unordered_map<uint, FilePath> &&filePathHash, SourceLocationsContainer(std::unordered_map<uint, FilePath> &&filePathHash,
std::vector<V2::SourceLocationContainer> &&sourceLocationContainers) std::vector<V2::SourceLocationContainer> &&sourceLocationContainers)
: filePathHash(std::move(filePathHash)), : SourceFilePathContainerBase(std::move(filePathHash)),
sourceLocationContainers_(std::move(sourceLocationContainers)) sourceLocationContainers_(std::move(sourceLocationContainers))
{} {}
@@ -61,21 +59,14 @@ public:
return !sourceLocationContainers_.empty(); return !sourceLocationContainers_.empty();
} }
void insertFilePath(uint fileId, Utils::SmallString &&fileDirectory, Utils::SmallString &&fileName) void insertSourceLocation(uint fileId, uint line, uint column, uint offset)
{ {
filePathHash.emplace(std::piecewise_construct, sourceLocationContainers_.emplace_back(fileId, line, column, offset);
std::forward_as_tuple(fileId),
std::forward_as_tuple(std::move(fileDirectory), std::move(fileName)));
}
void insertSourceLocation(uint fileId, uint line, uint column)
{
sourceLocationContainers_.emplace_back(fileId, line, column);
} }
void reserve(std::size_t size) void reserve(std::size_t size)
{ {
filePathHash.reserve(size / 3); SourceFilePathContainerBase::reserve(size);
sourceLocationContainers_.reserve(size); sourceLocationContainers_.reserve(size);
} }
@@ -105,14 +96,6 @@ public:
return SourceLocationsContainer(Utils::clone(filePathHash), Utils::clone(sourceLocationContainers_)); return SourceLocationsContainer(Utils::clone(filePathHash), Utils::clone(sourceLocationContainers_));
} }
const std::unordered_map<uint, FilePath> &filePathsForTestOnly() const
{
return filePathHash;
}
private:
std::unordered_map<uint, FilePath> filePathHash;
std::vector<V2::SourceLocationContainer> sourceLocationContainers_; std::vector<V2::SourceLocationContainer> sourceLocationContainers_;
}; };

View File

@@ -93,7 +93,7 @@ public:
private: private:
Utils::SmallString symbolName_; Utils::SmallString symbolName_;
SourceLocationsContainer sourceLocationContainer; SourceLocationsContainer sourceLocationContainer;
int revision; int revision = 0;
}; };
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const SourceLocationsForRenamingMessage &message); CMBIPC_EXPORT QDebug operator<<(QDebug debug, const SourceLocationsForRenamingMessage &message);

View File

@@ -0,0 +1,56 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "sourcerangecontainerv2.h"
#include <QDebug>
#include <ostream>
namespace ClangBackEnd {
namespace V2 {
QDebug operator<<(QDebug debug, const SourceRangeContainer &container)
{
debug.nospace() << "SourceRangeContainer("
<< container.start() << ", "
<< container.end()
<< ")";
return debug;
}
void PrintTo(const SourceRangeContainer &container, ::std::ostream* os)
{
*os << "(("
<< container.start().line() << ", "
<< container.start().column() << "), ("
<< container.end().line() << ", "
<< container.end().column()
<< "))";
}
} // namespace V2
} // namespace ClangBackEnd

View File

@@ -0,0 +1,105 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "sourcelocationcontainerv2.h"
namespace ClangBackEnd {
namespace V2 {
class SourceRangeContainer
{
public:
SourceRangeContainer() = default;
SourceRangeContainer(SourceLocationContainer start,
SourceLocationContainer end)
: start_(start),
end_(end)
{
}
SourceRangeContainer(uint fileHash,
uint startLine,
uint startColumn,
uint startOffset,
uint endLine,
uint endColumn,
uint endOffset)
: start_(fileHash, startLine, startColumn, startOffset),
end_(fileHash, endLine, endColumn, endOffset)
{
}
SourceLocationContainer start() const
{
return start_;
}
SourceLocationContainer end() const
{
return end_;
}
uint fileHash() const
{
return start_.fileHash();
}
friend QDataStream &operator<<(QDataStream &out, const SourceRangeContainer &container)
{
out << container.start_;
out << container.end_;
return out;
}
friend QDataStream &operator>>(QDataStream &in, SourceRangeContainer &container)
{
in >> container.start_;
in >> container.end_;
return in;
}
friend bool operator==(const SourceRangeContainer &first, const SourceRangeContainer &second)
{
return first.start_ == second.start_ && first.end_ == second.end_;
}
SourceRangeContainer clone() const
{
return SourceRangeContainer(start_.clone(), end_.clone());
}
private:
SourceLocationContainer start_;
SourceLocationContainer end_;
};
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const SourceRangeContainer &container);
void PrintTo(const SourceRangeContainer &container, ::std::ostream* os);
} // namespace V2
} // namespace ClangBackEnd

View File

@@ -0,0 +1,50 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "sourcerangesanddiagnosticsforquerymessage.h"
namespace ClangBackEnd {
QDebug operator<<(QDebug debug, const SourceRangesAndDiagnosticsForQueryMessage &message)
{
debug.nospace() << "SourceRangesAndDiagnosticsForQueryMessage("
<< message.sourceRanges() << ", "
<< message.diagnostics() << ")";
return debug;
}
void PrintTo(const SourceRangesAndDiagnosticsForQueryMessage &message, ::std::ostream* os)
{
Q_UNUSED(message)
Q_UNUSED(os)
#ifdef UNIT_TESTS
*os << "SourceRangesAndDiagnosticsForQueryMessage("
<< testing::PrintToString(message.sourceRanges()) << ", "
<< testing::PrintToString(message.diagnostics()) << ")";
#endif
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,93 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "sourcerangescontainer.h"
#include "dynamicastmatcherdiagnosticcontainer.h"
#include <utils/smallstring.h>
namespace ClangBackEnd {
class SourceRangesAndDiagnosticsForQueryMessage
{
public:
SourceRangesAndDiagnosticsForQueryMessage() = default;
SourceRangesAndDiagnosticsForQueryMessage(SourceRangesContainer &&sourceRangesContainer,
std::vector<DynamicASTMatcherDiagnosticContainer> &&diagnosticContainers)
: sourceRangesContainer(std::move(sourceRangesContainer)),
diagnosticContainers(std::move(diagnosticContainers))
{}
const SourceRangesContainer &sourceRanges() const
{
return sourceRangesContainer;
}
const std::vector<DynamicASTMatcherDiagnosticContainer> &diagnostics() const
{
return diagnosticContainers;
}
friend QDataStream &operator<<(QDataStream &out, const SourceRangesAndDiagnosticsForQueryMessage &message)
{
out << message.sourceRangesContainer;
out << message.diagnosticContainers;
return out;
}
friend QDataStream &operator>>(QDataStream &in, SourceRangesAndDiagnosticsForQueryMessage &message)
{
in >> message.sourceRangesContainer;
in >> message.diagnosticContainers;
return in;
}
friend bool operator==(const SourceRangesAndDiagnosticsForQueryMessage &first, const SourceRangesAndDiagnosticsForQueryMessage &second)
{
return first.sourceRangesContainer == second.sourceRangesContainer
&& first.diagnosticContainers == second.diagnosticContainers;
}
SourceRangesAndDiagnosticsForQueryMessage clone() const
{
return SourceRangesAndDiagnosticsForQueryMessage(sourceRangesContainer.clone(),
Utils::clone(diagnosticContainers));
}
private:
SourceRangesContainer sourceRangesContainer;
std::vector<DynamicASTMatcherDiagnosticContainer> diagnosticContainers;
};
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const SourceRangesAndDiagnosticsForQueryMessage &message);
void PrintTo(const SourceRangesAndDiagnosticsForQueryMessage &message, ::std::ostream* os);
DECLARE_MESSAGE(SourceRangesAndDiagnosticsForQueryMessage)
} // namespace ClangBackEnd

View File

@@ -0,0 +1,61 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "sourcerangescontainer.h"
namespace ClangBackEnd {
QDebug operator<<(QDebug debug, const SourceRangesContainer &container)
{
debug.nospace() << "SourceRangesContainer([";
for (const auto &sourceRangeWithText: container.sourceRangeWithTextContainers()) {
debug.nospace() << "["
<< container.filePathForSourceRange(sourceRangeWithText).name() << ", ("
<< sourceRangeWithText.start().line() << ","
<< sourceRangeWithText.start().column() << "), ("
<< sourceRangeWithText.end().line() << ","
<< sourceRangeWithText.end().column() << ")], ";
}
debug.nospace() << "])";
return debug;
}
void PrintTo(const SourceRangesContainer &container, ::std::ostream* os)
{
*os << "SourceRangesContainer(";
for (const auto &sourceRangeWithText: container.sourceRangeWithTextContainers()) {
*os << "["
<< container.filePathForSourceRange(sourceRangeWithText).name() << ","
<< sourceRangeWithText.start().line() << ","
<< sourceRangeWithText.start().column() << "), ("
<< sourceRangeWithText.end().line() << ","
<< sourceRangeWithText.end().column() << ")], ";
}
*os << ")";
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,125 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "sourcefilepathcontainerbase.h"
#include "sourcerangewithtextcontainer.h"
#include <utils/smallstringvector.h>
namespace ClangBackEnd {
class SourceRangesContainer : public SourceFilePathContainerBase
{
public:
SourceRangesContainer() = default;
SourceRangesContainer(std::unordered_map<uint, FilePath> &&filePathHash,
std::vector<SourceRangeWithTextContainer> &&sourceRangeWithTextContainers)
: SourceFilePathContainerBase(std::move(filePathHash)),
sourceRangeWithTextContainers_(std::move(sourceRangeWithTextContainers))
{}
const FilePath &filePathForSourceRange(const SourceRangeWithTextContainer &sourceRange) const
{
auto found = filePathHash.find(sourceRange.fileHash());
return found->second;
}
const std::vector<SourceRangeWithTextContainer> &sourceRangeWithTextContainers() const
{
return sourceRangeWithTextContainers_;
}
std::vector<SourceRangeWithTextContainer> takeSourceRangeWithTextContainers()
{
return std::move(sourceRangeWithTextContainers_);
}
bool hasContent() const
{
return !sourceRangeWithTextContainers_.empty();
}
void insertSourceRange(uint fileId,
uint startLine,
uint startColumn,
uint startOffset,
uint endLine,
uint endColumn,
uint endOffset,
Utils::SmallString &&text)
{
sourceRangeWithTextContainers_.emplace_back(fileId,
startLine,
startColumn,
startOffset,
endLine,
endColumn,
endOffset,
std::move(text));
}
void reserve(std::size_t size)
{
SourceFilePathContainerBase::reserve(size);
sourceRangeWithTextContainers_.reserve(size);
}
friend QDataStream &operator<<(QDataStream &out, const SourceRangesContainer &container)
{
out << container.filePathHash;
out << container.sourceRangeWithTextContainers_;
return out;
}
friend QDataStream &operator>>(QDataStream &in, SourceRangesContainer &container)
{
in >> container.filePathHash;
in >> container.sourceRangeWithTextContainers_;
return in;
}
friend bool operator==(const SourceRangesContainer &first, const SourceRangesContainer &second)
{
return first.sourceRangeWithTextContainers_ == second.sourceRangeWithTextContainers_;
}
SourceRangesContainer clone() const
{
return SourceRangesContainer(Utils::clone(filePathHash), Utils::clone(sourceRangeWithTextContainers_));
}
std::vector<SourceRangeWithTextContainer> sourceRangeWithTextContainers_;
};
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const SourceRangesContainer &container);
void PrintTo(const SourceRangesContainer &container, ::std::ostream* os);
} // namespace ClangBackEnd

View File

@@ -0,0 +1,51 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "sourcerangewithtextcontainer.h"
namespace ClangBackEnd {
QDebug operator<<(QDebug debug, const SourceRangeWithTextContainer &container)
{
debug.nospace() << "SourceRangeWithTextContainer("
<< container.start() << ", "
<< container.end() << ", "
<< container.text()
<< ")";
return debug;
}
void PrintTo(const SourceRangeWithTextContainer &container, ::std::ostream* os)
{
*os << "(("
<< container.start().line() << ", "
<< container.start().column() << "), ("
<< container.end().line() << ", "
<< container.end().column() << ", "
<< "\"" << container.text() << "\""
<< "))";
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,115 @@
/****************************************************************************
**
** Copyright (C) 2016 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 <sourcerangecontainerv2.h>
#include <utils/smallstringio.h>
namespace ClangBackEnd {
class SourceRangeWithTextContainer : V2::SourceRangeContainer
{
public:
SourceRangeWithTextContainer() = default;
SourceRangeWithTextContainer(uint fileHash,
uint startLine,
uint startColumn,
uint startOffset,
uint endLine,
uint endColumn,
uint endOffset,
Utils::SmallString &&text)
: V2::SourceRangeContainer(fileHash,
startLine,
startColumn,
startOffset,
endLine,
endColumn,
endOffset),
text_(std::move(text))
{}
SourceRangeWithTextContainer(V2::SourceRangeContainer &&base,
Utils::SmallString &&text)
: V2::SourceRangeContainer(std::move(base)),
text_(std::move(text))
{
}
const Utils::SmallString &text() const
{
return text_;
}
using V2::SourceRangeContainer::start;
using V2::SourceRangeContainer::end;
using V2::SourceRangeContainer::fileHash;
friend QDataStream &operator<<(QDataStream &out, const SourceRangeWithTextContainer &container)
{
out << container.base();
out << container.text_;
return out;
}
friend QDataStream &operator>>(QDataStream &in, SourceRangeWithTextContainer &container)
{
in >> container.base();
in >> container.text_;
return in;
}
friend bool operator==(const SourceRangeWithTextContainer &first,
const SourceRangeWithTextContainer &second)
{
return first.base() == second.base() && first.text_ == second.text_;
}
V2::SourceRangeContainer &base()
{
return *this;
}
const V2::SourceRangeContainer &base() const
{
return *this;
}
SourceRangeWithTextContainer clone() const
{
return SourceRangeWithTextContainer(base().clone(), text_.clone());
}
private:
Utils::SmallString text_;
};
CMBIPC_EXPORT QDebug operator<<(QDebug debug, const SourceRangeWithTextContainer &container);
void PrintTo(const SourceRangeWithTextContainer &container, ::std::ostream* os);
} // namespace ClangBackEnd

View File

@@ -0,0 +1,128 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "clangquerycurrentfilefindfilter.h"
#include "projectpartutilities.h"
#include "refactoringclient.h"
#include "refactoringcompileroptionsbuilder.h"
#include "searchinterface.h"
#include <refactoringserverinterface.h>
#include <requestsourcerangesanddiagnosticsforquerymessage.h>
namespace ClangRefactoring {
ClangQueryCurrentFileFindFilter::ClangQueryCurrentFileFindFilter(
ClangBackEnd::RefactoringServerInterface &server,
SearchInterface &searchInterface,
RefactoringClient &refactoringClient)
: server(server),
searchInterface(searchInterface),
refactoringClient(refactoringClient)
{
}
QString ClangQueryCurrentFileFindFilter::id() const
{
return QStringLiteral("Clang Query Current File");
}
QString ClangQueryCurrentFileFindFilter::displayName() const
{
return tr("Clang Query Current File");
}
bool ClangQueryCurrentFileFindFilter::isEnabled() const
{
return true;
}
void ClangQueryCurrentFileFindFilter::findAll(const QString &queryText, Core::FindFlags)
{
searchHandle = searchInterface.startNewSearch(tr("Clang Query"), queryText);
refactoringClient.setSearchHandle(searchHandle.get());
server.requestSourceRangesAndDiagnosticsForQueryMessage(createMessage(queryText));
}
Core::FindFlags ClangQueryCurrentFileFindFilter::supportedFindFlags() const
{
return 0;
}
void ClangQueryCurrentFileFindFilter::setCurrentDocumentFilePath(const QString &filePath)
{
currentDocumentFilePath = filePath;
}
void ClangQueryCurrentFileFindFilter::setUnsavedDocumentContent(const QString &unsavedContent)
{
unsavedDocumentContent = unsavedContent;
}
void ClangQueryCurrentFileFindFilter::setProjectPart(const CppTools::ProjectPart::Ptr &projectPart)
{
this->projectPart = projectPart;
}
void ClangQueryCurrentFileFindFilter::setUsable(bool isUsable)
{
server.setUsable(isUsable);
}
bool ClangQueryCurrentFileFindFilter::isUsable() const
{
return server.isUsable();
}
ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage
ClangQueryCurrentFileFindFilter::createMessage(const QString &queryText) const
{
std::vector<ClangBackEnd::V2::FileContainer> fileContainers;
fileContainers.emplace_back(ClangBackEnd::FilePath(currentDocumentFilePath),
unsavedDocumentContent,
createCommandLine());
return ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage(
Utils::SmallString(queryText),
std::move(fileContainers));
}
Utils::SmallStringVector ClangQueryCurrentFileFindFilter::createCommandLine() const
{
using ClangRefactoring::RefactoringCompilerOptionsBuilder;
auto commandLine = RefactoringCompilerOptionsBuilder::build(projectPart.data(),
fileKindInProjectPart(projectPart.data(),
currentDocumentFilePath));
commandLine.push_back(currentDocumentFilePath);
return commandLine;
}
} // namespace ClangRefactoring

View File

@@ -0,0 +1,82 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "searchhandleinterface.h"
#include <cpptools/projectpart.h>
#include <coreplugin/find/ifindfilter.h>
#include <utils/smallstringvector.h>
namespace ClangBackEnd {
class RefactoringServerInterface;
class RequestSourceRangesAndDiagnosticsForQueryMessage;
}
namespace ClangRefactoring {
class RefactoringClient;
class SearchInterface;
class ClangQueryCurrentFileFindFilter : public Core::IFindFilter
{
public:
ClangQueryCurrentFileFindFilter(ClangBackEnd::RefactoringServerInterface &server,
SearchInterface &searchInterface,
RefactoringClient &refactoringClient);
QString id() const;
QString displayName() const;
bool isEnabled() const;
void findAll(const QString &queryText, Core::FindFlags findFlags = 0);
Core::FindFlags supportedFindFlags() const;
void setCurrentDocumentFilePath(const QString &filePath);
void setUnsavedDocumentContent(const QString &unsavedContent);
void setCurrentDocumentRevision(int revision);
void setProjectPart(const CppTools::ProjectPart::Ptr &projectPart);
void setUsable(bool isUsable);
bool isUsable() const;
private:
ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage createMessage(
const QString &queryText) const;
Utils::SmallStringVector createCommandLine() const;
private:
QString currentDocumentFilePath;
QString unsavedDocumentContent;
std::unique_ptr<SearchHandleInterface> searchHandle;
CppTools::ProjectPart::Ptr projectPart;
ClangBackEnd::RefactoringServerInterface &server;
SearchInterface &searchInterface;
RefactoringClient &refactoringClient;
};
} // namespace ClangRefactoring

View File

@@ -0,0 +1,84 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "clangqueryprojectsfindfilter.h"
#include "refactoringclient.h"
#include "searchinterface.h"
#include <refactoringserverinterface.h>
namespace ClangRefactoring {
ClangQueryProjectsFindFilter::ClangQueryProjectsFindFilter(
ClangBackEnd::RefactoringServerInterface &server,
SearchInterface &searchInterface,
RefactoringClient &refactoringClient)
: server(server),
searchInterface(searchInterface),
refactoringClient(refactoringClient)
{
}
QString ClangQueryProjectsFindFilter::id() const
{
return QStringLiteral("Clang Query Project");
}
QString ClangQueryProjectsFindFilter::displayName() const
{
return tr("Clang Query Project");
}
bool ClangQueryProjectsFindFilter::isEnabled() const
{
return true;
}
void ClangQueryProjectsFindFilter::findAll(const QString &queryText, Core::FindFlags)
{
searchHandle = searchInterface.startNewSearch(tr("Clang Query"), queryText);
refactoringClient.setSearchHandle(searchHandle.get());
//server.requestSourceRangesAndDiagnosticsForQueryMessage(createMessage(queryText));
}
Core::FindFlags ClangQueryProjectsFindFilter::supportedFindFlags() const
{
return 0;
}
bool ClangQueryProjectsFindFilter::isUsable() const
{
return server.isUsable();
}
void ClangQueryProjectsFindFilter::setUsable(bool isUsable)
{
server.setUsable(isUsable);
}
} // namespace ClangRefactoring

View File

@@ -0,0 +1,67 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "searchhandleinterface.h"
#include <coreplugin/find/ifindfilter.h>
#include <memory>
namespace ClangBackEnd {
class RefactoringServerInterface;
class RequestSourceRangesAndDiagnosticsForQueryMessage;
}
namespace ClangRefactoring {
class RefactoringClient;
class SearchInterface;
class ClangQueryProjectsFindFilter : public Core::IFindFilter
{
public:
ClangQueryProjectsFindFilter(ClangBackEnd::RefactoringServerInterface &server,
SearchInterface &searchInterface,
RefactoringClient &refactoringClient);
QString id() const;
QString displayName() const;
bool isEnabled() const;
void findAll(const QString &queryText, Core::FindFlags findFlags = 0);
Core::FindFlags supportedFindFlags() const;
bool isUsable() const;
void setUsable(bool isUsable);
private:
std::unique_ptr<SearchHandleInterface> searchHandle;
ClangBackEnd::RefactoringServerInterface &server;
SearchInterface &searchInterface;
RefactoringClient &refactoringClient;
};
} // namespace ClangRefactoring

View File

@@ -4,10 +4,20 @@ HEADERS += \
$$PWD/refactoringengine.h \ $$PWD/refactoringengine.h \
$$PWD/refactoringconnectionclient.h \ $$PWD/refactoringconnectionclient.h \
$$PWD/refactoringcompileroptionsbuilder.h \ $$PWD/refactoringcompileroptionsbuilder.h \
$$PWD/refactoringclient.h $$PWD/refactoringclient.h \
$$PWD/searchinterface.h \
$$PWD/searchhandleinterface.h \
$$PWD/projectpartutilities.h \
$$PWD/clangquerycurrentfilefindfilter.h \
$$PWD/clangqueryprojectsfindfilter.h
SOURCES += \ SOURCES += \
$$PWD/refactoringengine.cpp \ $$PWD/refactoringengine.cpp \
$$PWD/refactoringconnectionclient.cpp \ $$PWD/refactoringconnectionclient.cpp \
$$PWD/refactoringcompileroptionsbuilder.cpp \ $$PWD/refactoringcompileroptionsbuilder.cpp \
$$PWD/refactoringclient.cpp $$PWD/refactoringclient.cpp \
$$PWD/searchinterface.cpp \
$$PWD/searchhandleinterface.cpp \
$$PWD/projectpartutilities.cpp \
$$PWD/clangquerycurrentfilefindfilter.cpp \
$$PWD/clangqueryprojectsfindfilter.cpp

View File

@@ -5,7 +5,13 @@ include(../../shared/clang/clang_installation.pri)
include(../../shared/clang/clang_defines.pri) include(../../shared/clang/clang_defines.pri)
HEADERS += \ HEADERS += \
$$PWD/clangrefactoringplugin.h $$PWD/clangrefactoringplugin.h \
qtcreatorsearch.h \
qtcreatorsearchhandle.h \
qtcreatorclangqueryfindfilter.h
SOURCES += \ SOURCES += \
$$PWD/clangrefactoringplugin.cpp $$PWD/clangrefactoringplugin.cpp \
qtcreatorsearch.cpp \
qtcreatorsearchhandle.cpp \
qtcreatorclangqueryfindfilter.cpp

View File

@@ -28,6 +28,8 @@
#include <cpptools/cppmodelmanager.h> #include <cpptools/cppmodelmanager.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/find/searchresultwindow.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/hostosinfo.h> #include <utils/hostosinfo.h>
@@ -44,17 +46,24 @@ QString backendProcessPath()
} // anonymous namespace } // anonymous namespace
std::unique_ptr<RefactoringClient> ClangRefactoringPlugin::client; std::unique_ptr<RefactoringClient> ClangRefactoringPlugin::refactoringClient;
std::unique_ptr<ClangBackEnd::RefactoringConnectionClient> ClangRefactoringPlugin::connectionClient; std::unique_ptr<ClangBackEnd::RefactoringConnectionClient> ClangRefactoringPlugin::connectionClient;
std::unique_ptr<RefactoringEngine> ClangRefactoringPlugin::engine; std::unique_ptr<RefactoringEngine> ClangRefactoringPlugin::engine;
std::unique_ptr<QtCreatorSearch> ClangRefactoringPlugin::qtCreatorSearch;
std::unique_ptr<QtCreatorClangQueryFindFilter> ClangRefactoringPlugin::qtCreatorfindFilter;
bool ClangRefactoringPlugin::initialize(const QStringList & /*arguments*/, QString * /*errorMessage*/) bool ClangRefactoringPlugin::initialize(const QStringList & /*arguments*/, QString * /*errorMessage*/)
{ {
client.reset(new RefactoringClient); refactoringClient.reset(new RefactoringClient);
connectionClient.reset(new ClangBackEnd::RefactoringConnectionClient(client.get())); connectionClient.reset(new ClangBackEnd::RefactoringConnectionClient(refactoringClient.get()));
engine.reset(new RefactoringEngine(connectionClient->serverProxy(), *client)); engine.reset(new RefactoringEngine(connectionClient->serverProxy(), *refactoringClient));
qtCreatorSearch.reset(new ClangRefactoring::QtCreatorSearch(*Core::SearchResultWindow::instance()));
qtCreatorfindFilter.reset(new QtCreatorClangQueryFindFilter(connectionClient->serverProxy(),
*qtCreatorSearch.get(),
*refactoringClient));
client->setRefactoringEngine(engine.get()); refactoringClient->setRefactoringEngine(engine.get());
ExtensionSystem::PluginManager::addObject(qtCreatorfindFilter.get());
connectBackend(); connectBackend();
startBackend(); startBackend();
@@ -69,13 +78,15 @@ void ClangRefactoringPlugin::extensionsInitialized()
ExtensionSystem::IPlugin::ShutdownFlag ClangRefactoringPlugin::aboutToShutdown() ExtensionSystem::IPlugin::ShutdownFlag ClangRefactoringPlugin::aboutToShutdown()
{ {
client->setRefactoringEngine(nullptr); ExtensionSystem::PluginManager::removeObject(qtCreatorfindFilter.get());
refactoringClient->setRefactoringEngine(nullptr);
connectionClient->finishProcess(); connectionClient->finishProcess();
qtCreatorfindFilter.reset();
engine.reset(); engine.reset();
connectionClient.reset(); connectionClient.reset();
client.reset(); refactoringClient.reset();
return SynchronousShutdown; return SynchronousShutdown;
} }

View File

@@ -27,6 +27,8 @@
#include "refactoringengine.h" #include "refactoringengine.h"
#include "refactoringclient.h" #include "refactoringclient.h"
#include "qtcreatorclangqueryfindfilter.h"
#include "qtcreatorsearch.h"
#include <refactoringconnectionclient.h> #include <refactoringconnectionclient.h>
#include <refactoringserverproxy.h> #include <refactoringserverproxy.h>
@@ -56,8 +58,11 @@ private:
private: private:
static std::unique_ptr<ClangBackEnd::RefactoringConnectionClient> connectionClient; static std::unique_ptr<ClangBackEnd::RefactoringConnectionClient> connectionClient;
static std::unique_ptr<RefactoringClient> client; static std::unique_ptr<RefactoringClient> refactoringClient;
static std::unique_ptr<RefactoringEngine> engine; static std::unique_ptr<RefactoringEngine> engine;
static std::unique_ptr<QtCreatorClangQueryFindFilter> qtCreatorfindFilter;
static std::unique_ptr<QtCreatorSearch> qtCreatorSearch;
}; };
} // namespace ClangRefactoring } // namespace ClangRefactoring

View File

@@ -0,0 +1,47 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "projectpartutilities.h"
namespace ClangRefactoring {
CppTools::ProjectFile::Kind fileKindInProjectPart(CppTools::ProjectPart *projectPart,
const QString &filePath)
{
const auto &projectFiles = projectPart->files;
auto comparePaths = [&] (const CppTools::ProjectFile &projectFile) {
return projectFile.path == filePath;
};
auto found = std::find_if(projectFiles.begin(), projectFiles.end(), comparePaths);
if (found != projectFiles.end())
return found->kind;
return CppTools::ProjectFile::Unclassified;
}
}

View File

@@ -0,0 +1,35 @@
/****************************************************************************
**
** Copyright (C) 2016 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 <cpptools/projectpart.h>
namespace ClangRefactoring {
CppTools::ProjectFile::Kind fileKindInProjectPart(CppTools::ProjectPart *projectPart,
const QString &filePath);
}

View File

@@ -0,0 +1,90 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "qtcreatorclangqueryfindfilter.h"
#include <texteditor/textdocument.h>
#include <cpptools/cppmodelmanager.h>
#include <cpptools/baseeditordocumentparser.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
namespace ClangRefactoring {
QtCreatorClangQueryFindFilter::QtCreatorClangQueryFindFilter(ClangBackEnd::RefactoringServerInterface &server,
SearchInterface &searchInterface,
RefactoringClient &refactoringClient)
: ClangQueryCurrentFileFindFilter(server, searchInterface, refactoringClient)
{
}
namespace {
CppTools::CppModelManager *cppToolManager()
{
return CppTools::CppModelManager::instance();
}
bool isCppEditor(Core::IEditor *currentEditor)
{
return cppToolManager()->isCppEditor(currentEditor);
}
CppTools::ProjectPart::Ptr projectPartForFile(const QString &filePath)
{
if (const auto parser = CppTools::BaseEditorDocumentParser::get(filePath))
return parser->projectPart();
return CppTools::ProjectPart::Ptr();
}
}
void QtCreatorClangQueryFindFilter::findAll(const QString &queryText, Core::FindFlags findFlags)
{
prepareFind();
ClangQueryCurrentFileFindFilter::findAll(queryText, findFlags);
}
void QtCreatorClangQueryFindFilter::prepareFind()
{
Core::IEditor *currentEditor = Core::EditorManager::currentEditor();
if (isCppEditor(currentEditor)) {
Core::IDocument *currentDocument = currentEditor->document();
auto currentTextDocument = static_cast<TextEditor::TextDocument*>(currentDocument);
const QString filePath = currentDocument->filePath().toString();
setCurrentDocumentFilePath(filePath);
setCurrentDocumentRevision(currentTextDocument->document()->revision());
setProjectPart(projectPartForFile(filePath));
if (currentTextDocument->isModified())
setUnsavedDocumentContent(currentTextDocument->document()->toPlainText());
}
}
} // namespace ClangRefactoring

View File

@@ -0,0 +1,45 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "clangquerycurrentfilefindfilter.h"
namespace ClangRefactoring {
class QtCreatorClangQueryFindFilter final : public ClangQueryCurrentFileFindFilter
{
public:
QtCreatorClangQueryFindFilter(ClangBackEnd::RefactoringServerInterface &server,
SearchInterface &searchInterface,
RefactoringClient &refactoringClient);
void findAll(const QString &queryText, Core::FindFlags findFlags = 0);
private:
void prepareFind();
};
} // namespace ClangRefactoring

View File

@@ -0,0 +1,50 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "qtcreatorsearch.h"
#include "qtcreatorsearchhandle.h"
namespace ClangRefactoring {
QtCreatorSearch::QtCreatorSearch(Core::SearchResultWindow &searchResultWindow)
: searchResultWindow(searchResultWindow)
{
}
std::unique_ptr<SearchHandleInterface> QtCreatorSearch::startNewSearch(const QString &searchLabel,
const QString &searchTerm)
{
Core::SearchResult *searchResult = searchResultWindow.startNewSearch(
searchLabel,
{},
searchTerm,
Core::SearchResultWindow::SearchOnly,
Core::SearchResultWindow::PreserveCaseEnabled);
return std::unique_ptr<SearchHandleInterface>(new QtCreatorSearchHandle(searchResult));
}
} // namespace ClangRefactoring

View File

@@ -0,0 +1,46 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "searchinterface.h"
#include <coreplugin/find/searchresultwindow.h>
namespace ClangRefactoring {
class QtCreatorSearch final : public SearchInterface
{
public:
QtCreatorSearch(Core::SearchResultWindow &searchResultWindow);
std::unique_ptr<SearchHandleInterface> startNewSearch(const QString &searchLabel,
const QString &searchTerm);
private:
Core::SearchResultWindow &searchResultWindow;
};
} // namespace ClangRefactoring

View File

@@ -0,0 +1,45 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "qtcreatorsearchhandle.h"
namespace ClangRefactoring {
QtCreatorSearchHandle::QtCreatorSearchHandle(Core::SearchResult *searchResult)
: searchResult(searchResult)
{
}
void QtCreatorSearchHandle::addResult(const QString &fileName, int lineNumber, const QString &lineText, int searchTermStart, int searchTermLength)
{
searchResult->addResult(fileName, lineNumber, lineText, searchTermStart, searchTermLength);
}
void QtCreatorSearchHandle::finishSearch()
{
searchResult->finishSearch(false);
}
} // namespace ClangRefactoring

View File

@@ -0,0 +1,51 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "searchhandleinterface.h"
#include <coreplugin/find/searchresultwindow.h>
namespace ClangRefactoring {
class QtCreatorSearchHandle final : public SearchHandleInterface
{
public:
QtCreatorSearchHandle(Core::SearchResult *searchResult);
void addResult(const QString &fileName,
int lineNumber,
const QString &lineText,
int searchTermStart,
int searchTermLength);
void finishSearch();
private:
Core::SearchResult *searchResult;
};
} // namespace ClangRefactoring

View File

@@ -26,6 +26,7 @@
#include "refactoringclient.h" #include "refactoringclient.h"
#include <sourcelocationsforrenamingmessage.h> #include <sourcelocationsforrenamingmessage.h>
#include <sourcerangesanddiagnosticsforquerymessage.h>
namespace ClangRefactoring { namespace ClangRefactoring {
@@ -34,7 +35,8 @@ void RefactoringClient::alive()
} }
void RefactoringClient::sourceLocationsForRenamingMessage(ClangBackEnd::SourceLocationsForRenamingMessage &&message) void RefactoringClient::sourceLocationsForRenamingMessage(
ClangBackEnd::SourceLocationsForRenamingMessage &&message)
{ {
localRenamingCallback(message.symbolName().toQString(), localRenamingCallback(message.symbolName().toQString(),
message.sourceLocations(), message.sourceLocations(),
@@ -43,7 +45,15 @@ void RefactoringClient::sourceLocationsForRenamingMessage(ClangBackEnd::SourceLo
refactoringEngine->setUsable(true); refactoringEngine->setUsable(true);
} }
void RefactoringClient::setLocalRenamingCallback(CppTools::RefactoringEngineInterface::RenameCallback &&localRenamingCallback) void RefactoringClient::sourceRangesAndDiagnosticsForQueryMessage(
ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage &&message)
{
addSearchResults(message.sourceRanges());
sendSearchIsFinished();
}
void RefactoringClient::setLocalRenamingCallback(
CppTools::RefactoringEngineInterface::RenameCallback &&localRenamingCallback)
{ {
this->localRenamingCallback = std::move(localRenamingCallback); this->localRenamingCallback = std::move(localRenamingCallback);
} }
@@ -53,9 +63,75 @@ void RefactoringClient::setRefactoringEngine(RefactoringEngine *refactoringEngin
this->refactoringEngine = refactoringEngine; this->refactoringEngine = refactoringEngine;
} }
void RefactoringClient::setSearchHandle(SearchHandleInterface *searchHandleInterface)
{
this->searchHandleInterface = searchHandleInterface;
}
SearchHandleInterface *RefactoringClient::searchHandle() const
{
return searchHandleInterface;
}
bool RefactoringClient::hasValidLocalRenamingCallback() const bool RefactoringClient::hasValidLocalRenamingCallback() const
{ {
return bool(localRenamingCallback); return bool(localRenamingCallback);
} }
namespace {
Utils::SmallString concatenateFilePath(const ClangBackEnd::FilePath &filePath)
{
Utils::SmallString concatenatedFilePath = filePath.directory().clone();
concatenatedFilePath.append("/");
concatenatedFilePath.append(filePath.name().clone());
return concatenatedFilePath;
}
}
std::unordered_map<uint, QString> RefactoringClient::convertFilePaths(
const ClangBackEnd::FilePathDict &filePaths)
{
using Dict = std::unordered_map<uint, QString>;
Dict qstringFilePaths;
qstringFilePaths.reserve(filePaths.size());
auto convertFilePath = [] (const ClangBackEnd::FilePathDict::value_type &dictonaryEntry) {
return std::make_pair(dictonaryEntry.first,
concatenateFilePath(dictonaryEntry.second).toQString());
};
std::transform(filePaths.begin(),
filePaths.end(),
std::inserter(qstringFilePaths, qstringFilePaths.begin()),
convertFilePath);
return qstringFilePaths;
}
void RefactoringClient::addSearchResults(const ClangBackEnd::SourceRangesContainer &sourceRanges)
{
auto filePaths = convertFilePaths(sourceRanges.filePaths());
for (const auto &sourceRangeWithText : sourceRanges.sourceRangeWithTextContainers())
addSearchResult(sourceRangeWithText, filePaths);
}
void RefactoringClient::addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRangeWithText,
std::unordered_map<uint, QString> &filePaths)
{
searchHandleInterface->addResult(filePaths[sourceRangeWithText.fileHash()],
int(sourceRangeWithText.start().line()),
sourceRangeWithText.text(),
int(sourceRangeWithText.start().column()),
int(sourceRangeWithText.end().column()));
}
void RefactoringClient::sendSearchIsFinished()
{
searchHandleInterface->finishSearch();
}
} // namespace ClangRefactoring } // namespace ClangRefactoring

View File

@@ -27,25 +27,48 @@
#include "refactoringengine.h" #include "refactoringengine.h"
#include <searchhandleinterface.h>
#include <refactoringclientinterface.h> #include <refactoringclientinterface.h>
#include <functional> #include <functional>
namespace ClangBackEnd {
class FilePath;
class SourceRangesContainer;
class SourceRangeWithTextContainer;
}
namespace ClangRefactoring { namespace ClangRefactoring {
class RefactoringClient : public ClangBackEnd::RefactoringClientInterface class RefactoringClient final : public ClangBackEnd::RefactoringClientInterface
{ {
public: public:
void alive() final; void alive() final;
void sourceLocationsForRenamingMessage(ClangBackEnd::SourceLocationsForRenamingMessage &&message) final; void sourceLocationsForRenamingMessage(
ClangBackEnd::SourceLocationsForRenamingMessage &&message) final;
void sourceRangesAndDiagnosticsForQueryMessage(
ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage &&message) final;
void setLocalRenamingCallback(CppTools::RefactoringEngineInterface::RenameCallback &&localRenamingCallback) final; void setLocalRenamingCallback(
CppTools::RefactoringEngineInterface::RenameCallback &&localRenamingCallback) final;
void setRefactoringEngine(ClangRefactoring::RefactoringEngine *refactoringEngine); void setRefactoringEngine(ClangRefactoring::RefactoringEngine *refactoringEngine);
void setSearchHandle(ClangRefactoring::SearchHandleInterface *searchHandleInterface);
ClangRefactoring::SearchHandleInterface *searchHandle() const;
bool hasValidLocalRenamingCallback() const; bool hasValidLocalRenamingCallback() const;
static std::unordered_map<uint, QString> convertFilePaths(
const std::unordered_map<uint, ClangBackEnd::FilePath> &filePaths);
private:
void addSearchResults(const ClangBackEnd::SourceRangesContainer &sourceRanges);
void addSearchResult(const ClangBackEnd::SourceRangeWithTextContainer &sourceRange,
std::unordered_map<uint, QString> &filePaths);
void sendSearchIsFinished();
private: private:
CppTools::RefactoringEngineInterface::RenameCallback localRenamingCallback; CppTools::RefactoringEngineInterface::RenameCallback localRenamingCallback;
ClangRefactoring::SearchHandleInterface *searchHandleInterface = nullptr;
ClangRefactoring::RefactoringEngine *refactoringEngine = nullptr; ClangRefactoring::RefactoringEngine *refactoringEngine = nullptr;
}; };

View File

@@ -25,6 +25,8 @@
#include "refactoringengine.h" #include "refactoringengine.h"
#include "projectpartutilities.h"
#include <refactoringcompileroptionsbuilder.h> #include <refactoringcompileroptionsbuilder.h>
#include <refactoringserverinterface.h> #include <refactoringserverinterface.h>
@@ -46,55 +48,22 @@ RefactoringEngine::RefactoringEngine(ClangBackEnd::RefactoringServerInterface &s
{ {
} }
namespace {
ClangBackEnd::FilePath convertToClangBackEndFilePath(const Utils::FileName &filePath)
{
Utils::SmallString utf8FilePath = filePath.toString();
auto found = std::find(utf8FilePath.rbegin(), utf8FilePath.rend(), '/').base();
Utils::SmallString fileName(found, utf8FilePath.end());
utf8FilePath.resize(std::size_t(std::distance(utf8FilePath.begin(), --found)));
return ClangBackEnd::FilePath(std::move(utf8FilePath), std::move(fileName));
}
CppTools::ProjectFile::Kind fileKind(CppTools::ProjectPart *projectPart, const QString &filePath)
{
const auto &projectFiles = projectPart->files;
auto comparePaths = [&] (const CppTools::ProjectFile &projectFile) {
return projectFile.path == filePath;
};
auto found = std::find_if(projectFiles.begin(), projectFiles.end(), comparePaths);
if (found != projectFiles.end())
return found->kind;
return CppTools::ProjectFile::Unclassified;
}
}
void RefactoringEngine::startLocalRenaming(const QTextCursor &textCursor, void RefactoringEngine::startLocalRenaming(const QTextCursor &textCursor,
const Utils::FileName &filePath, const Utils::FileName &filePath,
int revision, int revision,
CppTools::ProjectPart *projectPart, CppTools::ProjectPart *projectPart,
RenameCallback &&renameSymbolsCallback) RenameCallback &&renameSymbolsCallback)
{ {
isUsable_ = false; setUsable(false);
client.setLocalRenamingCallback(std::move(renameSymbolsCallback)); client.setLocalRenamingCallback(std::move(renameSymbolsCallback));
auto commandLine = RefactoringCompilerOptionsBuilder::build(projectPart, auto commandLine = RefactoringCompilerOptionsBuilder::build(projectPart,
fileKind(projectPart, filePath.toString())); fileKindInProjectPart(projectPart, filePath.toString()));
commandLine.push_back(filePath.toString()); commandLine.push_back(filePath.toString());
qDebug() << commandLine.join(" ");
RequestSourceLocationsForRenamingMessage message(convertToClangBackEndFilePath(filePath), RequestSourceLocationsForRenamingMessage message(ClangBackEnd::FilePath(filePath.toString()),
uint(textCursor.blockNumber() + 1), uint(textCursor.blockNumber() + 1),
uint(textCursor.positionInBlock() + 1), uint(textCursor.positionInBlock() + 1),
textCursor.document()->toPlainText(), textCursor.document()->toPlainText(),
@@ -107,12 +76,12 @@ void RefactoringEngine::startLocalRenaming(const QTextCursor &textCursor,
bool RefactoringEngine::isUsable() const bool RefactoringEngine::isUsable() const
{ {
return isUsable_; return server.isUsable();
} }
void RefactoringEngine::setUsable(bool isUsable) void RefactoringEngine::setUsable(bool isUsable)
{ {
isUsable_ = isUsable; server.setUsable(isUsable);
} }
} // namespace ClangRefactoring } // namespace ClangRefactoring

View File

@@ -51,7 +51,6 @@ public:
private: private:
ClangBackEnd::RefactoringServerInterface &server; ClangBackEnd::RefactoringServerInterface &server;
ClangBackEnd::RefactoringClientInterface &client; ClangBackEnd::RefactoringClientInterface &client;
bool isUsable_ = false;
}; };
} // namespace ClangRefactoring } // namespace ClangRefactoring

View File

@@ -0,0 +1,39 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "searchhandleinterface.h"
namespace ClangRefactoring {
SearchHandleInterface::SearchHandleInterface()
{
}
SearchHandleInterface::~SearchHandleInterface()
{
}
} // namespace ClangRefactoring

View File

@@ -0,0 +1,47 @@
/****************************************************************************
**
** Copyright (C) 2016 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 <QString>
namespace ClangRefactoring {
class SearchHandleInterface
{
public:
SearchHandleInterface();
virtual ~SearchHandleInterface();
virtual void addResult(const QString &fileName,
int lineNumber,
const QString &lineText,
int searchTermStart,
int searchTermLength) = 0;
virtual void finishSearch() = 0;
};
} // namespace ClangRefactoring

View File

@@ -0,0 +1,31 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "searchinterface.h"
namespace ClangRefactoring {
} // namespace ClangRefactoring

View File

@@ -0,0 +1,45 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "searchhandleinterface.h"
#include <QString>
#include <memory>
namespace ClangRefactoring {
class SearchInterface
{
public:
virtual ~SearchInterface() {}
virtual std::unique_ptr<SearchHandleInterface> startNewSearch(const QString &searchLabel,
const QString &searchTerm) = 0;
};
} // namespace ClangRefactoring

View File

@@ -1,7 +1,11 @@
DEFINES += CORE_STATIC_LIBRARY DEFINES += CORE_STATIC_LIBRARY
HEADERS += \ HEADERS += \
$$PWD/id.h $$PWD/coreicons.h \
$$PWD/id.h \
$$PWD/find/ifindfilter.h
SOURCES += \ SOURCES += \
$$PWD/id.cpp $$PWD/coreicons.cpp \
$$PWD/id.cpp \
$$PWD/find/ifindfilter.cpp

View File

@@ -0,0 +1,25 @@
/****************************************************************************
**
** Copyright (C) 2016 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.
**
****************************************************************************/

View File

@@ -0,0 +1,29 @@
/****************************************************************************
**
** Copyright (C) 2016 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.
**
****************************************************************************/
#ifndef ISEARCHRESULT_H
#define ISEARCHRESULT_H
#endif // ISEARCHRESULT_H

View File

@@ -34,11 +34,6 @@
namespace CppTools { namespace CppTools {
ProjectFile::ProjectFile()
: kind(CHeader)
{
}
ProjectFile::ProjectFile(const QString &file, Kind kind) ProjectFile::ProjectFile(const QString &file, Kind kind)
: path(file) : path(file)
, kind(kind) , kind(kind)

View File

@@ -51,7 +51,7 @@ public:
OpenCLSource = 10 OpenCLSource = 10
}; };
ProjectFile(); ProjectFile() = default;
ProjectFile(const QString &file, Kind kind); ProjectFile(const QString &file, Kind kind);
static Kind classify(const QString &file); static Kind classify(const QString &file);
@@ -59,7 +59,7 @@ public:
static bool isSource(Kind kind); static bool isSource(Kind kind);
QString path; QString path;
Kind kind; Kind kind = CHeader;
}; };
QDebug operator<<(QDebug stream, const CppTools::ProjectFile &cxxFile); QDebug operator<<(QDebug stream, const CppTools::ProjectFile &cxxFile);

View File

@@ -64,8 +64,9 @@ defineReplace(findClangOnWindows) {
} }
CLANGTOOLING_LIBS=-lclangTooling -lclangIndex -lclangFrontend -lclangParse -lclangSerialization \ CLANGTOOLING_LIBS=-lclangTooling -lclangIndex -lclangFrontend -lclangParse -lclangSerialization \
-lclangSema -lclangEdit -lclangAnalysis -lclangDriver -lclangASTMatchers \ -lclangSema -lclangEdit -lclangAnalysis -lclangDriver -lclangDynamicASTMatchers \
-lclangToolingCore -lclangAST -lclangLex -lclangBasic -lclangASTMatchers -lclangToolingCore -lclangAST -lclangLex -lclangBasic
win32:CLANGTOOLING_LIBS += -lversion
BIN_EXTENSION = BIN_EXTENSION =
win32: BIN_EXTENSION = .exe win32: BIN_EXTENSION = .exe

View File

@@ -0,0 +1,225 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "clangquery.h"
#include "sourcelocationsutils.h"
#include <sourcerangescontainer.h>
#include <QTime>
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
#include <clang/ASTMatchers/ASTMatchers.h>
#include <clang/ASTMatchers/ASTMatchFinder.h>
#include <clang/ASTMatchers/Dynamic/Diagnostics.h>
#include <clang/ASTMatchers/Dynamic/Parser.h>
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
using clang::ast_matchers::dynamic::Diagnostics;
using clang::ast_matchers::dynamic::Parser;
using clang::ast_matchers::BoundNodes;
using clang::ast_matchers::MatchFinder;
namespace ClangBackEnd {
struct CollectBoundNodes : MatchFinder::MatchCallback {
std::vector<BoundNodes> &Bindings;
CollectBoundNodes(std::vector<BoundNodes> &Bindings) : Bindings(Bindings) {}
void run(const MatchFinder::MatchResult &Result) override {
Bindings.push_back(Result.Nodes);
}
};
ClangQuery::ClangQuery(Utils::SmallString &&query)
: query(std::move(query))
{
}
void ClangQuery::setQuery(Utils::SmallString &&query)
{
this->query = std::move(query);
}
void ClangQuery::findLocations()
{
auto tool = createTool();
std::vector<std::unique_ptr<clang::ASTUnit>> asts;
{
QTime timer;
timer.start();
tool.buildASTs(asts);
qWarning() << "ASTs are built: " << timer.elapsed();
}
std::vector<clang::SourceRange> sourceRanges;
sourceRanges.reserve(100);
std::for_each (std::make_move_iterator(asts.begin()),
std::make_move_iterator(asts.end()),
[&] (std::unique_ptr<clang::ASTUnit> &&ast) {
Diagnostics diagnostics;
auto optionalMatcher = Parser::parseMatcherExpression({query.data(), query.size()},
nullptr,
&diagnostics);
parseDiagnostics(diagnostics);
matchLocation(optionalMatcher, std::move(ast), sourceRanges);
});
}
SourceRangesContainer ClangQuery::takeSourceRanges()
{
return std::move(sourceRangesContainer);
}
std::vector<DynamicASTMatcherDiagnosticContainer> ClangQuery::takeDiagnosticContainers()
{
return std::move(diagnosticContainers_);
}
namespace {
V2::SourceRangeContainer convertToContainer(const clang::ast_matchers::dynamic::SourceRange sourceRange)
{
return V2::SourceRangeContainer(0,
sourceRange.Start.Line,
sourceRange.Start.Column,
0,
sourceRange.End.Line,
sourceRange.End.Column,
0);
}
#define ERROR_RETURN_CASE(name) \
case Diagnostics::ET_##name: return ClangQueryDiagnosticErrorType::name;
ClangQueryDiagnosticErrorType convertToErrorType(Diagnostics::ErrorType clangErrorType)
{
switch (clangErrorType) {
ERROR_RETURN_CASE(None)
ERROR_RETURN_CASE(RegistryMatcherNotFound)
ERROR_RETURN_CASE(RegistryWrongArgCount)
ERROR_RETURN_CASE(RegistryWrongArgType)
ERROR_RETURN_CASE(RegistryNotBindable)
ERROR_RETURN_CASE(RegistryAmbiguousOverload)
ERROR_RETURN_CASE(RegistryValueNotFound)
ERROR_RETURN_CASE(ParserStringError)
ERROR_RETURN_CASE(ParserNoOpenParen)
ERROR_RETURN_CASE(ParserNoCloseParen)
ERROR_RETURN_CASE(ParserNoComma)
ERROR_RETURN_CASE(ParserNoCode)
ERROR_RETURN_CASE(ParserNotAMatcher)
ERROR_RETURN_CASE(ParserInvalidToken)
ERROR_RETURN_CASE(ParserMalformedBindExpr)
ERROR_RETURN_CASE(ParserTrailingCode)
ERROR_RETURN_CASE(ParserUnsignedError)
ERROR_RETURN_CASE(ParserOverloadedType)
}
Q_UNREACHABLE();
}
#define CONTEXT_RETURN_CASE(name) \
case Diagnostics::CT_##name: return ClangQueryDiagnosticContextType::name;
ClangQueryDiagnosticContextType convertToContextType(Diagnostics::ContextType clangContextType)
{
switch (clangContextType) {
CONTEXT_RETURN_CASE(MatcherArg)
CONTEXT_RETURN_CASE(MatcherConstruct)
}
Q_UNREACHABLE();
}
}
void ClangQuery::parseDiagnostics(const clang::ast_matchers::dynamic::Diagnostics &diagnostics)
{
auto errors = diagnostics.errors();
for (const auto &errorContent : errors) {
diagnosticContainers_.emplace_back();
DynamicASTMatcherDiagnosticContainer &diagnosticContainer = diagnosticContainers_.back();
for (const auto &message : errorContent.Messages) {
diagnosticContainer.insertMessage(convertToContainer(message.Range),
convertToErrorType(message.Type),
Utils::SmallStringVector(message.Args));
}
for (const auto &message : errorContent.ContextStack) {
diagnosticContainer.insertContext(convertToContainer(message.Range),
convertToContextType(message.Type),
Utils::SmallStringVector(message.Args));
}
}
}
void ClangQuery::matchLocation(
const llvm::Optional< clang::ast_matchers::internal::DynTypedMatcher> &optionalStartMatcher,
std::unique_ptr<clang::ASTUnit> ast,
std::vector<clang::SourceRange> &sourceRanges)
{
if (optionalStartMatcher) {
auto matcher = *optionalStartMatcher;
auto optionalMatcher = matcher.tryBind("root");
matcher = *optionalMatcher;
MatchFinder finder;
std::vector<BoundNodes> matches;
CollectBoundNodes collectBoundNodes(matches);
finder.addDynamicMatcher(matcher, &collectBoundNodes);
finder.matchAST(ast->getASTContext());
for (const auto &boundNodes : matches) {
for (const auto &mapEntry : boundNodes.getMap()) {
const auto sourceRange = mapEntry.second.getSourceRange();
if (sourceRange.isValid())
sourceRanges.push_back(sourceRange);
}
}
appendSourceRangesToSourceRangesContainer(sourceRangesContainer,
sourceRanges,
ast->getSourceManager());
}
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,73 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "clangtool.h"
#include <sourcerangescontainer.h>
#include <dynamicastmatcherdiagnosticcontainer.h>
namespace clang {
namespace ast_matchers {
namespace dynamic {
class Diagnostics;
}
namespace internal {
class DynTypedMatcher;
}
}
class SourceManager;
}
namespace ClangBackEnd {
class ClangQuery : public ClangTool
{
public:
ClangQuery(Utils::SmallString &&query={});
void setQuery(Utils::SmallString &&query);
void findLocations();
SourceRangesContainer takeSourceRanges();
std::vector<DynamicASTMatcherDiagnosticContainer> takeDiagnosticContainers();
private:
void parseDiagnostics(const clang::ast_matchers::dynamic::Diagnostics &diagnostics);
void matchLocation(const llvm::Optional< clang::ast_matchers::internal::DynTypedMatcher> &optionalStartMatcher,
std::unique_ptr<clang::ASTUnit> ast,
std::vector<clang::SourceRange> &sourceRanges);
private:
SourceRangesContainer sourceRangesContainer;
Utils::SmallString query;
std::vector<DynamicASTMatcherDiagnosticContainer> diagnosticContainers_;
};
} // namespace ClangBackEnd

View File

@@ -7,7 +7,9 @@ SOURCES += \
$$PWD/refactoringserver.cpp \ $$PWD/refactoringserver.cpp \
$$PWD/sourcefilecallbacks.cpp \ $$PWD/sourcefilecallbacks.cpp \
$$PWD/macropreprocessorcallbacks.cpp \ $$PWD/macropreprocessorcallbacks.cpp \
$$PWD/findusrforcursoraction.cpp $$PWD/findusrforcursoraction.cpp \
$$PWD/clangquery.cpp \
$$PWD/clangtool.cpp
HEADERS += \ HEADERS += \
$$PWD/refactoringcompilationdatabase.h \ $$PWD/refactoringcompilationdatabase.h \
@@ -20,4 +22,6 @@ HEADERS += \
$$PWD/sourcelocationsutils.h \ $$PWD/sourcelocationsutils.h \
$$PWD/findcursorusr.h \ $$PWD/findcursorusr.h \
$$PWD/findusrforcursoraction.h \ $$PWD/findusrforcursoraction.h \
$$PWD/findlocationsofusrs.h $$PWD/findlocationsofusrs.h \
$$PWD/clangquery.h \
$$PWD/clangtool.h

View File

@@ -0,0 +1,72 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "clangtool.h"
namespace ClangBackEnd {
namespace {
// use std::filesystem::path if it is supported by all compilers
std::string toNativePath(std::string &&path)
{
#ifdef WIN32
std::replace(path.begin(), path.end(), '/', '\\');
#endif
return std::move(path);
}
}
void ClangTool::addFile(std::string &&directory,
std::string &&fileName,
std::string &&content,
std::vector<std::string> &&commandLine)
{
fileContents.emplace_back(toNativePath(std::move(directory)),
std::move(fileName),
std::move(content),
std::move(commandLine));
const auto &fileContent = fileContents.back();
compilationDatabase.addFile(fileContent.directory, fileContent.fileName, fileContent.commandLine);
sourceFilePaths.push_back(fileContent.filePath);
}
clang::tooling::ClangTool ClangTool::createTool() const
{
clang::tooling::ClangTool tool(compilationDatabase, sourceFilePaths);
for (auto &&fileContent : fileContents) {
if (!fileContent.content.empty())
tool.mapVirtualFile(fileContent.filePath, fileContent.content);
}
return tool;
}
} // namespace ClangBackEnd

View File

@@ -0,0 +1,86 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "refactoringcompilationdatabase.h"
#include <clangrefactoringbackend_global.h>
#include <sourcelocationscontainer.h>
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
#include "clang/Tooling/Refactoring.h"
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
#include <string>
#include <vector>
namespace ClangBackEnd {
struct FileContent
{
FileContent(const std::string &directory,
const std::string &fileName,
const std::string &content,
const std::vector<std::string> &commandLine)
: directory(directory),
fileName(fileName),
filePath(directory + nativeSeperator + fileName),
content(content),
commandLine(commandLine)
{}
std::string directory;
std::string fileName;
std::string filePath;
std::string content;
std::vector<std::string> commandLine;
};
class ClangTool
{
public:
void addFile(std::string &&directory,
std::string &&fileName,
std::string &&content,
std::vector<std::string> &&commandLine);
clang::tooling::ClangTool createTool() const;
private:
RefactoringCompilationDatabase compilationDatabase;
std::vector<FileContent> fileContents;
std::vector<std::string> sourceFilePaths;
};
} // namespace ClangBackEnd

View File

@@ -26,18 +26,24 @@
#include "refactoringserver.h" #include "refactoringserver.h"
#include "symbolfinder.h" #include "symbolfinder.h"
#include "clangquery.h"
#include <refactoringclientinterface.h> #include <refactoringclientinterface.h>
#include <requestsourcelocationforrenamingmessage.h> #include <requestsourcelocationforrenamingmessage.h>
#include <requestsourcerangesanddiagnosticsforquerymessage.h>
#include <sourcelocationsforrenamingmessage.h> #include <sourcelocationsforrenamingmessage.h>
#include <sourcerangesanddiagnosticsforquerymessage.h>
#include <QCoreApplication> #include <QCoreApplication>
#include <algorithm>
#include <chrono>
#include <future>
namespace ClangBackEnd { namespace ClangBackEnd {
RefactoringServer::RefactoringServer() RefactoringServer::RefactoringServer()
{ {
} }
void RefactoringServer::end() void RefactoringServer::end()
@@ -56,10 +62,86 @@ void RefactoringServer::requestSourceLocationsForRenamingMessage(RequestSourceLo
symbolFinder.findSymbol(); symbolFinder.findSymbol();
client()->sourceLocationsForRenamingMessage(SourceLocationsForRenamingMessage( client()->sourceLocationsForRenamingMessage({symbolFinder.takeSymbolName(),
symbolFinder.takeSymbolName(), symbolFinder.takeSourceLocations(),
symbolFinder.takeSourceLocations(), message.textDocumentRevision()});
message.textDocumentRevision())); }
namespace {
SourceRangesAndDiagnosticsForQueryMessage createSourceRangesAndDiagnosticsForQueryMessage(
V2::FileContainer &&fileContainer,
Utils::SmallString &&query) {
ClangQuery clangQuery(std::move(query));
clangQuery.addFile(fileContainer.filePath().directory(),
fileContainer.filePath().name(),
fileContainer.takeUnsavedFileContent(),
fileContainer.takeCommandLineArguments());
clangQuery.findLocations();
return {clangQuery.takeSourceRanges(), clangQuery.takeDiagnosticContainers()};
}
}
void RefactoringServer::requestSourceRangesAndDiagnosticsForQueryMessage(
RequestSourceRangesAndDiagnosticsForQueryMessage &&message)
{
gatherSourceRangesAndDiagnosticsForQueryMessage(message.takeFileContainers(), message.takeQuery());
}
void RefactoringServer::gatherSourceRangesAndDiagnosticsForQueryMessage(
std::vector<V2::FileContainer> &&fileContainers,
Utils::SmallString &&query)
{
std::vector<Future> futures;
std::size_t freeProcessors = std::thread::hardware_concurrency();
while (!fileContainers.empty() || !futures.empty()) {
--freeProcessors;
if (!fileContainers.empty()) {
Future &&future = std::async(std::launch::async,
createSourceRangesAndDiagnosticsForQueryMessage,
std::move(fileContainers.back()),
query.clone());
fileContainers.pop_back();
futures.emplace_back(std::move(future));
}
if (freeProcessors == 0 || fileContainers.empty())
freeProcessors += waitForNewSourceRangesAndDiagnosticsForQueryMessage(futures);
}
}
std::size_t RefactoringServer::waitForNewSourceRangesAndDiagnosticsForQueryMessage(std::vector<Future> &futures)
{
while (true) {
std::vector<Future> readyFutures;
readyFutures.reserve(futures.size());
auto beginReady = std::partition(futures.begin(),
futures.end(),
[] (const Future &future) {
return future.wait_for(std::chrono::duration<int>::zero()) != std::future_status::ready;
});
std::move(beginReady, futures.end(), std::back_inserter(readyFutures));
futures.erase(beginReady, futures.end());
for (Future &readyFuture : readyFutures)
client()->sourceRangesAndDiagnosticsForQueryMessage(std::move(readyFuture.get()));
if (readyFutures.empty())
std::this_thread::sleep_for(std::chrono::milliseconds(20));
else
return readyFutures.size();
}
} }
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -23,22 +23,35 @@
** **
****************************************************************************/ ****************************************************************************/
#ifndef CLANGBACKEND_REFACTORINGSERVER_H #pragma once
#define CLANGBACKEND_REFACTORINGSERVER_H
#include <refactoringserverinterface.h> #include <refactoringserverinterface.h>
#include <future>
#include <vector>
namespace ClangBackEnd { namespace ClangBackEnd {
class SourceRangesAndDiagnosticsForQueryMessage;
namespace V2 {
class FileContainer;
}
class RefactoringServer : public RefactoringServerInterface class RefactoringServer : public RefactoringServerInterface
{ {
using Future = std::future<SourceRangesAndDiagnosticsForQueryMessage>;
public: public:
RefactoringServer(); RefactoringServer();
void end() override; void end() override;
void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override; void requestSourceLocationsForRenamingMessage(RequestSourceLocationsForRenamingMessage &&message) override;
void requestSourceRangesAndDiagnosticsForQueryMessage(RequestSourceRangesAndDiagnosticsForQueryMessage &&message) override;
private:
void gatherSourceRangesAndDiagnosticsForQueryMessage(std::vector<V2::FileContainer> &&fileContainers,
Utils::SmallString &&query);
std::size_t waitForNewSourceRangesAndDiagnosticsForQueryMessage(std::vector<Future> &futures);
}; };
} // namespace ClangBackEnd } // namespace ClangBackEnd
#endif // CLANGBACKEND_REFACTORINGSERVER_H

View File

@@ -26,6 +26,7 @@
#pragma once #pragma once
#include <sourcelocationscontainer.h> #include <sourcelocationscontainer.h>
#include <sourcerangescontainer.h>
#if defined(__GNUC__) #if defined(__GNUC__)
#pragma GCC diagnostic push #pragma GCC diagnostic push
@@ -40,6 +41,8 @@
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif
#include <cctype>
namespace ClangBackEnd { namespace ClangBackEnd {
inline inline
@@ -65,6 +68,75 @@ Utils::SmallString fromNativePath(Container container)
return path; return path;
} }
inline Utils::SmallString getSourceText(const clang::FullSourceLoc &startFullSourceLocation,
uint startOffset,
uint endOffset)
{
auto startBuffer = startFullSourceLocation.getBufferData();
const auto bufferSize = endOffset - startOffset;
return Utils::SmallString(startBuffer.data() + startOffset, bufferSize + 1);
}
inline void makePrintable(Utils::SmallString &text)
{
text.replace("\n", " ");
text.replace("\t", " ");
auto end = std::unique(text.begin(), text.end(), [](char l, char r){
return std::isspace(l) && std::isspace(r) && l == r;
});
text.resize(std::distance(text.begin(), end));
}
inline void appendSourceRangeToSourceRangesContainer(
const clang::SourceRange &sourceRange,
ClangBackEnd::SourceRangesContainer &sourceRangesContainer,
const clang::SourceManager &sourceManager)
{
clang::FullSourceLoc startFullSourceLocation(sourceRange.getBegin(), sourceManager);
clang::FullSourceLoc endFullSourceLocation(sourceRange.getEnd(), sourceManager);
if (startFullSourceLocation.isFileID() && endFullSourceLocation.isFileID()) {
const auto startDecomposedLoction = startFullSourceLocation.getDecomposedLoc();
const auto endDecomposedLoction = endFullSourceLocation.getDecomposedLoc();
const auto fileId = startDecomposedLoction.first;
const auto startOffset = startDecomposedLoction.second;
const auto endOffset = endDecomposedLoction.second;
const auto fileEntry = sourceManager.getFileEntryForID(fileId);
auto filePath = absolutePath(fileEntry->getName());
const auto fileName = llvm::sys::path::filename(filePath);
llvm::sys::path::remove_filename(filePath);
Utils::SmallString content = getSourceText(startFullSourceLocation,
startOffset,
endOffset);
makePrintable(content);
sourceRangesContainer.insertFilePath(fileId.getHashValue(),
fromNativePath(filePath),
fromNativePath(fileName));
sourceRangesContainer.insertSourceRange(fileId.getHashValue(),
startFullSourceLocation.getSpellingLineNumber(),
startFullSourceLocation.getSpellingColumnNumber(),
startOffset,
endFullSourceLocation.getSpellingLineNumber(),
endFullSourceLocation.getSpellingColumnNumber(),
endOffset,
std::move(content));
}
}
inline
void appendSourceRangesToSourceRangesContainer(
ClangBackEnd::SourceRangesContainer &sourceRangesContainer,
const std::vector<clang::SourceRange> &sourceRanges,
const clang::SourceManager &sourceManager)
{
sourceRangesContainer.reserve(sourceRanges.size());
for (const auto &sourceRange : sourceRanges)
appendSourceRangeToSourceRangesContainer(sourceRange, sourceRangesContainer, sourceManager);
}
inline inline
void appendSourceLocationsToSourceLocationsContainer( void appendSourceLocationsToSourceLocationsContainer(
ClangBackEnd::SourceLocationsContainer &sourceLocationsContainer, ClangBackEnd::SourceLocationsContainer &sourceLocationsContainer,
@@ -75,10 +147,12 @@ void appendSourceLocationsToSourceLocationsContainer(
for (const auto &sourceLocation : sourceLocations) { for (const auto &sourceLocation : sourceLocations) {
clang::FullSourceLoc fullSourceLocation(sourceLocation, sourceManager); clang::FullSourceLoc fullSourceLocation(sourceLocation, sourceManager);
auto fileId = fullSourceLocation.getFileID(); const auto decomposedLoction = fullSourceLocation.getDecomposedLoc();
auto fileEntry = sourceManager.getFileEntryForID(fileId); const auto fileId = decomposedLoction.first;
const auto offset = decomposedLoction.second;
const auto fileEntry = sourceManager.getFileEntryForID(fileId);
auto filePath = absolutePath(fileEntry->getName()); auto filePath = absolutePath(fileEntry->getName());
auto fileName = llvm::sys::path::filename(filePath); const auto fileName = llvm::sys::path::filename(filePath);
llvm::sys::path::remove_filename(filePath); llvm::sys::path::remove_filename(filePath);
sourceLocationsContainer.insertFilePath(fileId.getHashValue(), sourceLocationsContainer.insertFilePath(fileId.getHashValue(),
@@ -86,8 +160,11 @@ void appendSourceLocationsToSourceLocationsContainer(
fromNativePath(fileName)); fromNativePath(fileName));
sourceLocationsContainer.insertSourceLocation(fileId.getHashValue(), sourceLocationsContainer.insertSourceLocation(fileId.getHashValue(),
fullSourceLocation.getSpellingLineNumber(), fullSourceLocation.getSpellingLineNumber(),
fullSourceLocation.getSpellingColumnNumber()); fullSourceLocation.getSpellingColumnNumber(),
offset);
} }
} }
} // namespace ClangBackEnd } // namespace ClangBackEnd

View File

@@ -25,7 +25,6 @@
#include "symbolfinder.h" #include "symbolfinder.h"
#include "refactoringcompilationdatabase.h"
#include "sourcefilecallbacks.h" #include "sourcefilecallbacks.h"
#include "symbollocationfinderaction.h" #include "symbollocationfinderaction.h"
@@ -37,49 +36,9 @@ SymbolFinder::SymbolFinder(uint line, uint column)
{ {
} }
namespace {
// use std::filesystem::path if it is supported by all compilers
std::string toNativePath(std::string &&path)
{
#ifdef WIN32
std::replace(path.begin(), path.end(), '/', '\\');
#endif
return std::move(path);
}
}
void SymbolFinder::addFile(std::string &&directory,
std::string &&fileName,
std::string &&content,
std::vector<std::string> &&commandLine)
{
fileContents.emplace_back(toNativePath(std::move(directory)),
std::move(fileName),
std::move(content),
std::move(commandLine));
}
void SymbolFinder::findSymbol() void SymbolFinder::findSymbol()
{ {
RefactoringCompilationDatabase compilationDatabase; clang::tooling::ClangTool tool = createTool();
for (auto &&fileContent : fileContents)
compilationDatabase.addFile(fileContent.directory, fileContent.fileName, fileContent.commandLine);
std::vector<std::string> files;
for (auto &&fileContent : fileContents)
files.push_back(fileContent.filePath);
clang::tooling::ClangTool tool(compilationDatabase, files);
for (auto &&fileContent : fileContents) {
if (!fileContent.content.empty())
tool.mapVirtualFile(fileContent.filePath, fileContent.content);
}
tool.run(clang::tooling::newFrontendActionFactory(&usrFindingAction, &sourceFileCallbacks).get()); tool.run(clang::tooling::newFrontendActionFactory(&usrFindingAction, &sourceFileCallbacks).get());

View File

@@ -25,6 +25,7 @@
#pragma once #pragma once
#include "clangtool.h"
#include "findusrforcursoraction.h" #include "findusrforcursoraction.h"
#include "symbollocationfinderaction.h" #include "symbollocationfinderaction.h"
#include "sourcefilecallbacks.h" #include "sourcefilecallbacks.h"
@@ -42,42 +43,13 @@
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif
#include <string>
#include <vector>
namespace ClangBackEnd { namespace ClangBackEnd {
struct FileContent class SymbolFinder : public ClangTool
{
FileContent(const std::string &directory,
const std::string &fileName,
const std::string &content,
const std::vector<std::string> &commandLine)
: directory(directory),
fileName(fileName),
filePath(directory + nativeSeperator + fileName),
content(content),
commandLine(commandLine)
{}
std::string directory;
std::string fileName;
std::string filePath;
std::string content;
std::vector<std::string> commandLine;
};
class SymbolFinder
{ {
public: public:
SymbolFinder(uint line, uint column); SymbolFinder(uint line, uint column);
void addFile(std::string &&directory,
std::string &&fileName,
std::string &&content,
std::vector<std::string> &&commandLine);
void findSymbol(); void findSymbol();
Utils::SmallString takeSymbolName(); Utils::SmallString takeSymbolName();
@@ -90,7 +62,7 @@ private:
USRFindingAction usrFindingAction; USRFindingAction usrFindingAction;
SymbolLocationFinderAction symbolLocationFinderAction; SymbolLocationFinderAction symbolLocationFinderAction;
SourceFileCallbacks sourceFileCallbacks; SourceFileCallbacks sourceFileCallbacks;
std::vector<FileContent> fileContents;
ClangBackEnd::SourceLocationsContainer sourceLocations_; ClangBackEnd::SourceLocationsContainer sourceLocations_;
}; };

View File

@@ -21,7 +21,7 @@ mac {
isEmpty(LLVM_INSTALL_DIR):LLVM_INSTALL_DIR=$$(LLVM_INSTALL_DIR) isEmpty(LLVM_INSTALL_DIR):LLVM_INSTALL_DIR=$$(LLVM_INSTALL_DIR)
exists($$LLVM_INSTALL_DIR) { exists($$LLVM_INSTALL_DIR) {
SUBDIRS += clangbackend SUBDIRS += clangbackend
# SUBDIRS += clangrefactoringbackend SUBDIRS += clangrefactoringbackend
} }
isEmpty(BUILD_CPLUSPLUS_TOOLS):BUILD_CPLUSPLUS_TOOLS=$$(BUILD_CPLUSPLUS_TOOLS) isEmpty(BUILD_CPLUSPLUS_TOOLS):BUILD_CPLUSPLUS_TOOLS=$$(BUILD_CPLUSPLUS_TOOLS)

View File

@@ -2,7 +2,6 @@ isEmpty(LLVM_INSTALL_DIR):LLVM_INSTALL_DIR=$$(LLVM_INSTALL_DIR)
!isEmpty(LLVM_INSTALL_DIR) { !isEmpty(LLVM_INSTALL_DIR) {
include(../../../src/shared/clang/clang_installation.pri) include(../../../src/shared/clang/clang_installation.pri)
requires(!isEmpty(LIBCLANG_LIBS)) requires(!isEmpty(LIBCLANG_LIBS))
equals(LLVM_IS_COMPILED_WITH_RTTI, "NO") : message("LLVM needs to be compiled with RTTI!") equals(LLVM_IS_COMPILED_WITH_RTTI, "NO") : message("LLVM needs to be compiled with RTTI!")
requires(equals(LLVM_IS_COMPILED_WITH_RTTI, "YES")) requires(equals(LLVM_IS_COMPILED_WITH_RTTI, "YES"))

View File

@@ -0,0 +1,165 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "googletest.h"
#include "sourcerangecontainer-matcher.h"
#include "dynamicastmatcherdiagnosticcontainer-matcher.h"
#include <clangquery.h>
using ClangBackEnd::ClangQuery;
using testing::IsEmpty;
using testing::Not;
using testing::AllOf;
namespace {
class ClangQuery : public ::testing::Test
{
protected:
void SetUp() override;
protected:
::ClangQuery simpleFunctionQuery;
::ClangQuery simpleClassQuery;
};
TEST_F(ClangQuery, NoSourceRangesForDefaultConstruction)
{
auto sourceRanges = simpleFunctionQuery.takeSourceRanges();
ASSERT_THAT(sourceRanges.sourceRangeWithTextContainers(), IsEmpty());
}
TEST_F(ClangQuery, SourceRangesForSimpleFunctionDeclarationAreNotEmpty)
{
simpleFunctionQuery.setQuery("functionDecl()");
simpleFunctionQuery.findLocations();
ASSERT_THAT(simpleFunctionQuery.takeSourceRanges().sourceRangeWithTextContainers(), Not(IsEmpty()));
}
TEST_F(ClangQuery, RootSourceRangeForSimpleFunctionDeclarationRange)
{
simpleFunctionQuery.setQuery("functionDecl()");
simpleFunctionQuery.findLocations();
ASSERT_THAT(simpleFunctionQuery.takeSourceRanges().sourceRangeWithTextContainers().at(0),
IsSourceRangeWithText(1, 1, 8, 1, "int function(int* pointer, int value) { if (pointer == nullptr) { return value + 1; } else { return value - 1; } }"));
}
TEST_F(ClangQuery, RootSourceRangeForSimpleFieldDeclarationRange)
{
simpleClassQuery.setQuery("fieldDecl(hasType(isInteger()))");
simpleClassQuery.findLocations();
ASSERT_THAT(simpleClassQuery.takeSourceRanges().sourceRangeWithTextContainers().at(0),
IsSourceRangeWithText(4, 5, 4, 9, "int x"));
}
TEST_F(ClangQuery, NoSourceRangesForEmptyQuery)
{
simpleClassQuery.findLocations();
ASSERT_THAT(simpleClassQuery.takeSourceRanges().sourceRangeWithTextContainers(), IsEmpty());
}
TEST_F(ClangQuery, NoSourceRangesForWrongQuery)
{
simpleClassQuery.setQuery("wrongQuery()");
simpleClassQuery.findLocations();
ASSERT_THAT(simpleClassQuery.takeSourceRanges().sourceRangeWithTextContainers(), IsEmpty());
}
TEST_F(ClangQuery, NoDiagnosticsForDefaultConstruction)
{
auto diagnostics = simpleFunctionQuery.takeDiagnosticContainers();
ASSERT_THAT(diagnostics, IsEmpty());
}
TEST_F(ClangQuery, DiagnosticsForEmptyQuery)
{
simpleFunctionQuery.findLocations();
ASSERT_THAT(simpleFunctionQuery.takeDiagnosticContainers(),
Not(IsEmpty()));
}
TEST_F(ClangQuery, DiagnosticsForWrongQuery)
{
simpleClassQuery.setQuery("wrongQuery()");
simpleClassQuery.findLocations();
ASSERT_THAT(simpleClassQuery.takeDiagnosticContainers(),
Not(IsEmpty()));
}
TEST_F(ClangQuery, NoDiagnosticsForAccurateQuery)
{
simpleFunctionQuery.setQuery("functionDecl()");
simpleFunctionQuery.findLocations();
ASSERT_THAT(simpleFunctionQuery.takeDiagnosticContainers(),
IsEmpty());
}
TEST_F(ClangQuery, DiagnosticForWrongQuery)
{
simpleClassQuery.setQuery("wrongQuery()");
simpleClassQuery.findLocations();
ASSERT_THAT(simpleClassQuery.takeDiagnosticContainers(),
HasDiagnosticMessage("RegistryMatcherNotFound", 1, 1, 1, 11));
}
TEST_F(ClangQuery, DiagnosticForWrongArgumenType)
{
simpleFunctionQuery.setQuery("functionDecl(1)");
simpleFunctionQuery.findLocations();
ASSERT_THAT(simpleFunctionQuery.takeDiagnosticContainers(),
AllOf(HasDiagnosticMessage("RegistryWrongArgType", 1, 14, 1, 15),
HasDiagnosticContext("MatcherConstruct", 1, 1, 1, 13)));
}
void ClangQuery::SetUp()
{
simpleFunctionQuery.addFile(TESTDATA_DIR, "query_simplefunction.cpp", "", {"cc", "query_simplefunction.cpp", "-std=c++14"});
simpleClassQuery.addFile(TESTDATA_DIR, "query_simpleclass.cpp", "", {"cc", "query_simpleclass.cpp", "-std=c++14"});
}
}

View File

@@ -0,0 +1,154 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "googletest.h"
#include "mockrefactoringserver.h"
#include "mocksearch.h"
#include "mocksearchhandle.h"
#include <clangquerycurrentfilefindfilter.h>
#include <refactoringcompileroptionsbuilder.h>
#include <refactoringclient.h>
#include <requestsourcelocationforrenamingmessage.h>
#include <requestsourcerangesanddiagnosticsforquerymessage.h>
#include <sourcelocationsforrenamingmessage.h>
#include <sourcerangesanddiagnosticsforquerymessage.h>
#include <cpptools/projectpart.h>
namespace {
using ::testing::_;
using ::testing::NiceMock;
using ::testing::NotNull;
using ::testing::ReturnNew;
using ::testing::DefaultValue;
using ClangRefactoring::RefactoringCompilerOptionsBuilder;
class ClangQueryCurrentFileFindFilter : public ::testing::Test
{
protected:
void SetUp();
protected:
NiceMock<MockRefactoringServer> mockRefactoringServer;
NiceMock<MockSearch> mockSearch;
ClangRefactoring::RefactoringClient refactoringClient;
ClangRefactoring::ClangQueryCurrentFileFindFilter findFilter{mockRefactoringServer, mockSearch, refactoringClient};
QString findDeclQueryText{"functionDecl()"};
QString curentDocumentFilePath{"/path/to/file.cpp"};
QString unsavedDocumentContent{"void f();"};
Utils::SmallStringVector commandLine;
CppTools::ProjectPart::Ptr projectPart;
CppTools::ProjectFile projectFile{curentDocumentFilePath, CppTools::ProjectFile::CXXSource};
};
TEST_F(ClangQueryCurrentFileFindFilter, SupportedFindFlags)
{
auto findFlags = findFilter.supportedFindFlags();
ASSERT_FALSE(findFlags);
}
TEST_F(ClangQueryCurrentFileFindFilter, IsNotUsableForUnusableServer)
{
auto isUsable = findFilter.isUsable();
ASSERT_FALSE(isUsable);
}
TEST_F(ClangQueryCurrentFileFindFilter, IsUsableForUsableServer)
{
mockRefactoringServer.setUsable(true);
auto isUsable = findFilter.isUsable();
ASSERT_TRUE(isUsable);
}
TEST_F(ClangQueryCurrentFileFindFilter, ServerIsUsableForUsableFindFilter)
{
findFilter.setUsable(true);
auto isUsable = mockRefactoringServer.isUsable();
ASSERT_TRUE(isUsable);
}
TEST_F(ClangQueryCurrentFileFindFilter, SearchHandleSetIsSetAfterFindAll)
{
findFilter.findAll(findDeclQueryText);
auto searchHandle = refactoringClient.searchHandle();
ASSERT_THAT(searchHandle, NotNull());
}
TEST_F(ClangQueryCurrentFileFindFilter, FindAllIsCallingStartNewSearch)
{
EXPECT_CALL(mockSearch, startNewSearch(QStringLiteral("Clang Query"),
findDeclQueryText))
.Times(1);
findFilter.findAll(findDeclQueryText);
}
TEST_F(ClangQueryCurrentFileFindFilter, FindAllIsCallingRequestSourceRangesAndDiagnosticsForQueryMessage)
{
ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage message(findDeclQueryText,
{{{"/path/to", "file.cpp"},
unsavedDocumentContent,
commandLine.clone(),
1}});
EXPECT_CALL(mockRefactoringServer, requestSourceRangesAndDiagnosticsForQueryMessage(message))
.Times(1);
findFilter.findAll(findDeclQueryText);
}
void ClangQueryCurrentFileFindFilter::SetUp()
{
projectPart = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart);
projectPart->files.push_back(projectFile);
commandLine = RefactoringCompilerOptionsBuilder::build(projectPart.data(),
projectFile.kind);
commandLine.push_back(curentDocumentFilePath);
findFilter.setCurrentDocumentFilePath(curentDocumentFilePath);
findFilter.setUnsavedDocumentContent(unsavedDocumentContent);
findFilter.setProjectPart(projectPart);
DefaultValue<std::unique_ptr<ClangRefactoring::SearchHandleInterface>>::SetFactory([] () {
return std::unique_ptr<ClangRefactoring::SearchHandleInterface>(new MockSearchHandle); });
}
}

View File

@@ -0,0 +1,153 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "googletest.h"
#include "mockrefactoringserver.h"
#include "mocksearch.h"
#include "mocksearchhandle.h"
#include <clangqueryprojectsfindfilter.h>
#include <refactoringclient.h>
#include <refactoringcompileroptionsbuilder.h>
#include <requestsourcelocationforrenamingmessage.h>
#include <requestsourcerangesanddiagnosticsforquerymessage.h>
#include <cpptools/projectpart.h>
namespace {
using ::testing::_;
using ::testing::NiceMock;
using ::testing::NotNull;
using ::testing::ReturnNew;
using ::testing::DefaultValue;
using ClangRefactoring::RefactoringCompilerOptionsBuilder;
class ClangQueryProjectFindFilter : public ::testing::Test
{
protected:
void SetUp();
protected:
NiceMock<MockRefactoringServer> mockRefactoringServer;
NiceMock<MockSearch> mockSearch;
ClangRefactoring::RefactoringClient refactoringClient;
ClangRefactoring::ClangQueryProjectsFindFilter findFilter{mockRefactoringServer, mockSearch, refactoringClient};
QString findDeclQueryText{"functionDecl()"};
QString curentDocumentFilePath{"/path/to/file.cpp"};
QString unsavedDocumentContent{"void f();"};
Utils::SmallStringVector commandLine;
CppTools::ProjectPart::Ptr projectPart1;
CppTools::ProjectPart::Ptr projectPart2;
CppTools::ProjectFile projectFile{curentDocumentFilePath, CppTools::ProjectFile::CXXSource};
};
TEST_F(ClangQueryProjectFindFilter, SupportedFindFlags)
{
auto findFlags = findFilter.supportedFindFlags();
ASSERT_FALSE(findFlags);
}
TEST_F(ClangQueryProjectFindFilter, IsNotUsableForUnusableServer)
{
auto isUsable = findFilter.isUsable();
ASSERT_FALSE(isUsable);
}
TEST_F(ClangQueryProjectFindFilter, IsUsableForUsableServer)
{
mockRefactoringServer.setUsable(true);
auto isUsable = findFilter.isUsable();
ASSERT_TRUE(isUsable);
}
TEST_F(ClangQueryProjectFindFilter, ServerIsUsableForUsableFindFilter)
{
findFilter.setUsable(true);
auto isUsable = mockRefactoringServer.isUsable();
ASSERT_TRUE(isUsable);
}
TEST_F(ClangQueryProjectFindFilter, SearchHandleSetIsSetAfterFindAll)
{
findFilter.findAll(findDeclQueryText);
auto searchHandle = refactoringClient.searchHandle();
ASSERT_THAT(searchHandle, NotNull());
}
TEST_F(ClangQueryProjectFindFilter, FindAllIsCallingStartNewSearch)
{
EXPECT_CALL(mockSearch, startNewSearch(QStringLiteral("Clang Query"),
findDeclQueryText))
.Times(1);
findFilter.findAll(findDeclQueryText);
}
TEST_F(ClangQueryProjectFindFilter, FindAllIsCallingRequestSourceRangesAndDiagnosticsForQueryMessage)
{
ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage message(findDeclQueryText,
{{{"/path/to", "file.cpp"},
unsavedDocumentContent,
commandLine.clone(),
1}});
EXPECT_CALL(mockRefactoringServer, requestSourceRangesAndDiagnosticsForQueryMessage(message))
.Times(1);
findFilter.findAll(findDeclQueryText);
}
void ClangQueryProjectFindFilter::SetUp()
{
// projectPart = CppTools::ProjectPart::Ptr(new CppTools::ProjectPart);
// projectPart->files.push_back(projectFile);
// commandLine = RefactoringCompilerOptionsBuilder::build(projectPart.data(),
// projectFile.kind);
commandLine.push_back(curentDocumentFilePath);
// findFilter.setCurrentDocumentFilePath(curentDocumentFilePath);
// findFilter.setCurrentDocumentRevision(documentRevision);
// findFilter.setUnsavedDocumentContent(unsavedDocumentContent);
// findFilter.setProjectPart(projectPart);
DefaultValue<std::unique_ptr<ClangRefactoring::SearchHandleInterface>>::SetFactory([] () {
return std::unique_ptr<ClangRefactoring::SearchHandleInterface>(new MockSearchHandle); });
}
}

View File

@@ -1,3 +1,4 @@
INCLUDEPATH += $$PWD INCLUDEPATH += $$PWD
include($$PWD/../../../src/libs/cplusplus/cplusplus-lib.pri) include($$PWD/../../../src/libs/cplusplus/cplusplus-lib.pri)

View File

@@ -0,0 +1,8 @@
class Class
{
public:
int x;
};

View File

@@ -0,0 +1,8 @@
int function(int* pointer, int value)
{
if (pointer == nullptr) {
return value + 1;
} else {
return value - 1;
}
}

View File

@@ -0,0 +1,84 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "googletest.h"
using testing::PrintToString;
namespace {
MATCHER_P5(HasDiagnosticMessage, errorTypeText, startLine, startColumn, endLine, endColumn,
std::string(negation ? "isn't " : "is ")
+ "{" + PrintToString(errorTypeText)
+ ": (" + PrintToString(startLine)
+ ", " + PrintToString(startColumn)
+ "), (" + PrintToString(endLine)
+ ", " + PrintToString(endColumn)
+ ")}"
)
{
if (!arg.empty() && arg.front().messages().empty()) {
*result_listener << "no messages";
return false;
}
auto message = arg.front().messages().front();
auto sourceRange = message.sourceRange();
return message.errorTypeText() == errorTypeText
&& sourceRange.start().line() == uint(startLine)
&& sourceRange.start().column() == uint(startColumn)
&& sourceRange.end().line() == uint(endLine)
&& sourceRange.end().column() == uint(endColumn);
}
MATCHER_P5(HasDiagnosticContext, contextTypeText, startLine, startColumn, endLine, endColumn,
std::string(negation ? "isn't " : "is ")
+ "{" + PrintToString(contextTypeText)
+ ": (" + PrintToString(startLine)
+ ", " + PrintToString(startColumn)
+ "), (" + PrintToString(endLine)
+ ", " + PrintToString(endColumn)
+ ")}"
)
{
if (!arg.empty() && arg.front().messages().empty()) {
*result_listener << "no context";
return false;
}
auto context = arg.front().contexts().front();
auto sourceRange = context.sourceRange();
return context.contextTypeText() == contextTypeText
&& sourceRange.start().line() == uint(startLine)
&& sourceRange.start().column() == uint(startColumn)
&& sourceRange.end().line() == uint(endLine)
&& sourceRange.end().column() == uint(endColumn);
}
}

View File

@@ -25,6 +25,8 @@
#pragma once #pragma once
#include "googletest.h"
#include <clangbackendipc/clangcodemodelclientinterface.h> #include <clangbackendipc/clangcodemodelclientinterface.h>
#include <clangbackendipc/cmbcodecompletedmessage.h> #include <clangbackendipc/cmbcodecompletedmessage.h>
#include <clangbackendipc/cmbechomessage.h> #include <clangbackendipc/cmbechomessage.h>
@@ -34,11 +36,6 @@
#include <clangbackendipc/updatetranslationunitsforeditormessage.h> #include <clangbackendipc/updatetranslationunitsforeditormessage.h>
#include <clangbackendipc/updatevisibletranslationunitsmessage.h> #include <clangbackendipc/updatevisibletranslationunitsmessage.h>
#include <gmock/gmock.h>
#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>
#include "gtest-qt-printing.h"
class MockClangCodeModelClient : public ClangBackEnd::ClangCodeModelClientInterface class MockClangCodeModelClient : public ClangBackEnd::ClangCodeModelClientInterface
{ {
public: public:

View File

@@ -32,19 +32,26 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "gtest-qt-printing.h" #include "gtest-qt-printing.h"
class MockRefactoringClient : public ClangBackEnd::RefactoringClientInterface class MockRefactoringClient final : public ClangBackEnd::RefactoringClientInterface
{ {
public: public:
MOCK_METHOD0(alive, MOCK_METHOD0(alive,
void()); void());
MOCK_METHOD1(sourceLocationsForRenamingMessage, MOCK_METHOD1(sourceLocationsForRenamingMessage,
void (const ClangBackEnd::SourceLocationsForRenamingMessage&)); void (const ClangBackEnd::SourceLocationsForRenamingMessage&));
MOCK_METHOD1(sourceRangesAndDiagnosticsForQueryMessage,
void (const ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage&));
void sourceLocationsForRenamingMessage(ClangBackEnd::SourceLocationsForRenamingMessage &&message) override void sourceLocationsForRenamingMessage(ClangBackEnd::SourceLocationsForRenamingMessage &&message) override
{ {
sourceLocationsForRenamingMessage(message); sourceLocationsForRenamingMessage(message);
} }
void sourceRangesAndDiagnosticsForQueryMessage(ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage &&message) override
{
sourceRangesAndDiagnosticsForQueryMessage(message);
}
void setLocalRenamingCallback(RenameCallback &&) void setLocalRenamingCallback(RenameCallback &&)
{ {
} }

View File

@@ -25,12 +25,9 @@
#pragma once #pragma once
#include <refactoringserverinterface.h> #include "googletest.h"
#include <gmock/gmock.h> #include <refactoringserverinterface.h>
#include <gmock/gmock-matchers.h>
#include <gtest/gtest.h>
#include "gtest-qt-printing.h"
class MockRefactoringServer : public ClangBackEnd::RefactoringServerInterface class MockRefactoringServer : public ClangBackEnd::RefactoringServerInterface
{ {
@@ -41,8 +38,16 @@ public:
MOCK_METHOD1(requestSourceLocationsForRenamingMessage, MOCK_METHOD1(requestSourceLocationsForRenamingMessage,
void (const ClangBackEnd::RequestSourceLocationsForRenamingMessage&)); void (const ClangBackEnd::RequestSourceLocationsForRenamingMessage&));
MOCK_METHOD1(requestSourceRangesAndDiagnosticsForQueryMessage,
void (const ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage&));
void requestSourceLocationsForRenamingMessage(ClangBackEnd::RequestSourceLocationsForRenamingMessage &&message) override void requestSourceLocationsForRenamingMessage(ClangBackEnd::RequestSourceLocationsForRenamingMessage &&message) override
{ {
requestSourceLocationsForRenamingMessage(message); requestSourceLocationsForRenamingMessage(message);
} }
void requestSourceRangesAndDiagnosticsForQueryMessage(ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage &&message) override
{
requestSourceRangesAndDiagnosticsForQueryMessage(message);
}
}; };

View File

@@ -0,0 +1,38 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "googletest.h"
#include <searchinterface.h>
class MockSearch : public ClangRefactoring::SearchInterface
{
public:
MOCK_METHOD2(startNewSearch,
std::unique_ptr<ClangRefactoring::SearchHandleInterface>(const QString &searchLabel,
const QString &searchTerm));
};

View File

@@ -0,0 +1,42 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "googletest.h"
#include <searchhandleinterface.h>
class MockSearchHandle : public ClangRefactoring::SearchHandleInterface
{
public:
MOCK_METHOD5(addResult,
void(const QString &fileName,
int lineNumber,
const QString &lineText,
int searchTermStart,
int searchTermLength));
MOCK_METHOD0(finishSearch, void());
};

View File

@@ -0,0 +1,28 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "googletest.h"

View File

@@ -25,6 +25,7 @@
#include "googletest.h" #include "googletest.h"
#include "mockrefactoringclientcallback.h" #include "mockrefactoringclientcallback.h"
#include "mocksearchhandle.h"
#include <refactoringclient.h> #include <refactoringclient.h>
#include <refactoringcompileroptionsbuilder.h> #include <refactoringcompileroptionsbuilder.h>
@@ -32,6 +33,7 @@
#include <refactoringconnectionclient.h> #include <refactoringconnectionclient.h>
#include <sourcelocationsforrenamingmessage.h> #include <sourcelocationsforrenamingmessage.h>
#include <sourcerangesanddiagnosticsforquerymessage.h>
#include <cpptools/projectpart.h> #include <cpptools/projectpart.h>
@@ -45,7 +47,13 @@ namespace {
using ClangRefactoring::RefactoringCompilerOptionsBuilder; using ClangRefactoring::RefactoringCompilerOptionsBuilder;
using ClangRefactoring::RefactoringEngine; using ClangRefactoring::RefactoringEngine;
using ClangBackEnd::SourceLocationsForRenamingMessage;
using ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage;
using testing::_; using testing::_;
using testing::Pair;
using testing::Contains;
using testing::NiceMock;
using Utils::SmallString; using Utils::SmallString;
using Utils::SmallStringVector; using Utils::SmallStringVector;
@@ -55,6 +63,7 @@ class RefactoringClient : public ::testing::Test
void SetUp(); void SetUp();
protected: protected:
NiceMock<MockSearchHandle> mockSearchHandle;
MockRefactoringClientCallBack callbackMock; MockRefactoringClientCallBack callbackMock;
ClangRefactoring::RefactoringClient client; ClangRefactoring::RefactoringClient client;
ClangBackEnd::RefactoringConnectionClient connectionClient{&client}; ClangBackEnd::RefactoringConnectionClient connectionClient{&client};
@@ -64,14 +73,20 @@ protected:
QTextCursor cursor{&textDocument}; QTextCursor cursor{&textDocument};
QString qStringFilePath{QStringLiteral("/home/user/file.cpp")}; QString qStringFilePath{QStringLiteral("/home/user/file.cpp")};
Utils::FileName filePath{Utils::FileName::fromString(qStringFilePath)}; Utils::FileName filePath{Utils::FileName::fromString(qStringFilePath)};
ClangBackEnd::FilePath clangBackEndFilePath{"/home/user", "file.cpp"}; ClangBackEnd::FilePath clangBackEndFilePath{qStringFilePath};
SmallStringVector commandLine; SmallStringVector commandLine;
CppTools::ProjectPart::Ptr projectPart; CppTools::ProjectPart::Ptr projectPart;
CppTools::ProjectFile projectFile{qStringFilePath, CppTools::ProjectFile::CXXSource}; CppTools::ProjectFile projectFile{qStringFilePath, CppTools::ProjectFile::CXXSource};
ClangBackEnd::SourceLocationsForRenamingMessage message{"symbol", SourceLocationsForRenamingMessage renameMessage{"symbol",
{{{42u, clangBackEndFilePath.clone()}}, {{{42u, clangBackEndFilePath.clone()}},
{{42u, 1, 1}, {42u, 2, 5}}}, {{42u, 1, 1, 0}, {42u, 2, 5, 10}}},
1}; 1};
SourceRangesAndDiagnosticsForQueryMessage queryResultMessage{{{{42u, clangBackEndFilePath.clone()}},
{{42u, 1, 1, 0, 1, 5, 4, ""},
{42u, 2, 1, 5, 2, 5, 10, ""}}},
{}};
SourceRangesAndDiagnosticsForQueryMessage emptyQueryResultMessage{{{},{}},
{}};
}; };
TEST_F(RefactoringClient, SourceLocationsForRenaming) TEST_F(RefactoringClient, SourceLocationsForRenaming)
@@ -84,12 +99,12 @@ TEST_F(RefactoringClient, SourceLocationsForRenaming)
textDocumentRevision); textDocumentRevision);
}); });
EXPECT_CALL(callbackMock, localRenaming(message.symbolName().toQString(), EXPECT_CALL(callbackMock, localRenaming(renameMessage.symbolName().toQString(),
message.sourceLocations(), renameMessage.sourceLocations(),
message.textDocumentRevision())) renameMessage.textDocumentRevision()))
.Times(1); .Times(1);
client.sourceLocationsForRenamingMessage(std::move(message)); client.sourceLocationsForRenamingMessage(std::move(renameMessage));
} }
TEST_F(RefactoringClient, AfterSourceLocationsForRenamingEngineIsUsableAgain) TEST_F(RefactoringClient, AfterSourceLocationsForRenamingEngineIsUsableAgain)
@@ -103,18 +118,65 @@ TEST_F(RefactoringClient, AfterSourceLocationsForRenamingEngineIsUsableAgain)
}); });
EXPECT_CALL(callbackMock, localRenaming(_,_,_)); EXPECT_CALL(callbackMock, localRenaming(_,_,_));
client.sourceLocationsForRenamingMessage(std::move(message)); client.sourceLocationsForRenamingMessage(std::move(renameMessage));
ASSERT_TRUE(engine.isUsable()); ASSERT_TRUE(engine.isUsable());
} }
TEST_F(RefactoringClient, AfterStartLocalRenameHasValidCallback) TEST_F(RefactoringClient, AfterStartLocalRenameHasValidCallback)
{ {
engine.startLocalRenaming(cursor, filePath, textDocument.revision(), projectPart.data(), {}); engine.startLocalRenaming(cursor,
filePath,
textDocument.revision(),
projectPart.data(),
[&] (const QString &,
const ClangBackEnd::SourceLocationsContainer &,
int) {});
ASSERT_TRUE(client.hasValidLocalRenamingCallback()); ASSERT_TRUE(client.hasValidLocalRenamingCallback());
} }
TEST_F(RefactoringClient, CallAddResultsForEmptyQueryMessage)
{
EXPECT_CALL(mockSearchHandle, addResult(_ ,_ ,_ , _, _))
.Times(0);
client.sourceRangesAndDiagnosticsForQueryMessage(std::move(emptyQueryResultMessage));
}
TEST_F(RefactoringClient, CallAddResultsForQueryMessage)
{
EXPECT_CALL(mockSearchHandle, addResult(_ ,_ ,_ , _, _))
.Times(2);
client.sourceRangesAndDiagnosticsForQueryMessage(std::move(queryResultMessage));
}
TEST_F(RefactoringClient, CallFinishSearchForEmptyQueryMessage)
{
EXPECT_CALL(mockSearchHandle, finishSearch())
.Times(1);
client.sourceRangesAndDiagnosticsForQueryMessage(std::move(emptyQueryResultMessage));
}
TEST_F(RefactoringClient, CallFinishSearchQueryMessage)
{
EXPECT_CALL(mockSearchHandle, finishSearch())
.Times(1);
client.sourceRangesAndDiagnosticsForQueryMessage(std::move(queryResultMessage));
}
TEST_F(RefactoringClient, ConvertFilePaths)
{
std::unordered_map<uint, ClangBackEnd::FilePath> filePaths{{42u, clangBackEndFilePath.clone()}};
auto qstringFilePaths = ClangRefactoring::RefactoringClient::convertFilePaths(filePaths);
ASSERT_THAT(qstringFilePaths, Contains(Pair(42u, qStringFilePath)));
}
void RefactoringClient::SetUp() void RefactoringClient::SetUp()
{ {
client.setRefactoringEngine(&engine); client.setRefactoringEngine(&engine);
@@ -124,6 +186,8 @@ void RefactoringClient::SetUp()
commandLine = RefactoringCompilerOptionsBuilder::build(projectPart.data(), commandLine = RefactoringCompilerOptionsBuilder::build(projectPart.data(),
projectFile.kind); projectFile.kind);
client.setSearchHandle(&mockSearchHandle);
} }
} }

View File

@@ -32,7 +32,9 @@
#include <refactoringclientproxy.h> #include <refactoringclientproxy.h>
#include <refactoringserverproxy.h> #include <refactoringserverproxy.h>
#include <sourcelocationsforrenamingmessage.h> #include <sourcelocationsforrenamingmessage.h>
#include <sourcerangesanddiagnosticsforquerymessage.h>
#include <requestsourcelocationforrenamingmessage.h> #include <requestsourcelocationforrenamingmessage.h>
#include <requestsourcerangesanddiagnosticsforquerymessage.h>
#include <QBuffer> #include <QBuffer>
#include <QString> #include <QString>
@@ -101,7 +103,7 @@ TEST_F(RefactoringClientServerInProcess, SendSourceLocationsForRenamingMessage)
TEST_F(RefactoringClientServerInProcess, SendRequestSourceLocationsForRenamingMessage) TEST_F(RefactoringClientServerInProcess, SendRequestSourceLocationsForRenamingMessage)
{ {
RequestSourceLocationsForRenamingMessage message{{"/home/marco/dev/qt-creator/tests/unit/unittest/data", "renamevariable.cpp"}, RequestSourceLocationsForRenamingMessage message{{TESTDATA_DIR, "renamevariable.cpp"},
1, 1,
5, 5,
"int v;\n\nint x = v + 3;\n", "int v;\n\nint x = v + 3;\n",
@@ -115,6 +117,35 @@ TEST_F(RefactoringClientServerInProcess, SendRequestSourceLocationsForRenamingMe
scheduleServerMessages(); scheduleServerMessages();
} }
TEST_F(RefactoringClientServerInProcess, SourceRangesAndDiagnosticsForQueryMessage)
{
ClangBackEnd::SourceRangesContainer sourceRangesContainer;
std::vector<ClangBackEnd::DynamicASTMatcherDiagnosticContainer> diagnosticContainers;
ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage message(std::move(sourceRangesContainer),
std::move(diagnosticContainers));
EXPECT_CALL(mockRefactoringClient, sourceRangesAndDiagnosticsForQueryMessage(message))
.Times(1);
clientProxy.sourceRangesAndDiagnosticsForQueryMessage(message.clone());
scheduleClientMessages();
}
TEST_F(RefactoringClientServerInProcess, RequestSourceRangesAndDiagnosticsForQueryMessage)
{
RequestSourceRangesAndDiagnosticsForQueryMessage message{"functionDecl()",
{{{TESTDATA_DIR, "query_simplefunction.cpp"},
"void f();",
{"cc", "query_simplefunction.cpp"},
1}}};
EXPECT_CALL(mockRefactoringServer, requestSourceRangesAndDiagnosticsForQueryMessage(message))
.Times(1);
serverProxy.requestSourceRangesAndDiagnosticsForQueryMessage(message.clone());
scheduleServerMessages();
}
RefactoringClientServerInProcess::RefactoringClientServerInProcess() RefactoringClientServerInProcess::RefactoringClientServerInProcess()
: serverProxy(&mockRefactoringClient, &buffer), : serverProxy(&mockRefactoringClient, &buffer),
clientProxy(&mockRefactoringServer, &buffer) clientProxy(&mockRefactoringServer, &buffer)

View File

@@ -32,7 +32,9 @@
#include <refactoringengine.h> #include <refactoringengine.h>
#include <requestsourcelocationforrenamingmessage.h> #include <requestsourcelocationforrenamingmessage.h>
#include <requestsourcerangesanddiagnosticsforquerymessage.h>
#include <sourcelocationsforrenamingmessage.h> #include <sourcelocationsforrenamingmessage.h>
#include <sourcerangesanddiagnosticsforquerymessage.h>
#include <cpptools/projectpart.h> #include <cpptools/projectpart.h>
@@ -66,7 +68,7 @@ protected:
QTextCursor cursor{&textDocument}; QTextCursor cursor{&textDocument};
QString qStringFilePath{QStringLiteral("/home/user/file.cpp")}; QString qStringFilePath{QStringLiteral("/home/user/file.cpp")};
Utils::FileName filePath{Utils::FileName::fromString(qStringFilePath)}; Utils::FileName filePath{Utils::FileName::fromString(qStringFilePath)};
ClangBackEnd::FilePath clangBackEndFilePath{"/home/user", "file.cpp"}; ClangBackEnd::FilePath clangBackEndFilePath{qStringFilePath};
SmallStringVector commandLine; SmallStringVector commandLine;
CppTools::ProjectPart::Ptr projectPart; CppTools::ProjectPart::Ptr projectPart;
CppTools::ProjectFile projectFile{qStringFilePath, CppTools::ProjectFile::CXXSource}; CppTools::ProjectFile projectFile{qStringFilePath, CppTools::ProjectFile::CXXSource};
@@ -97,6 +99,25 @@ TEST_F(RefactoringEngine, AfterSendRequestSourceLocationsForRenamingMessageIsUnu
ASSERT_FALSE(engine.isUsable()); ASSERT_FALSE(engine.isUsable());
} }
TEST_F(RefactoringEngine, EngineIsNotUsableForUnusableServer)
{
ASSERT_FALSE(engine.isUsable());
}
TEST_F(RefactoringEngine, EngineIsUsableForUsableServer)
{
mockRefactoringServer.setUsable(true);
ASSERT_TRUE(engine.isUsable());
}
TEST_F(RefactoringEngine, ServerIsUsableForUsableEngine)
{
engine.setUsable(true);
ASSERT_TRUE(mockRefactoringServer.isUsable());
}
RefactoringEngine::RefactoringEngine() RefactoringEngine::RefactoringEngine()
: engine(mockRefactoringServer, mockRefactoringClient) : engine(mockRefactoringServer, mockRefactoringClient)
{ {

View File

@@ -26,10 +26,13 @@
#include "googletest.h" #include "googletest.h"
#include "mockrefactoringclient.h" #include "mockrefactoringclient.h"
#include "sourcerangecontainer-matcher.h"
#include <refactoringserver.h> #include <refactoringserver.h>
#include <requestsourcelocationforrenamingmessage.h> #include <requestsourcelocationforrenamingmessage.h>
#include <requestsourcerangesanddiagnosticsforquerymessage.h>
#include <sourcelocationsforrenamingmessage.h> #include <sourcelocationsforrenamingmessage.h>
#include <sourcerangesanddiagnosticsforquerymessage.h>
#include <sourcelocationscontainer.h> #include <sourcelocationscontainer.h>
namespace { namespace {
@@ -41,22 +44,24 @@ using testing::PrintToString;
using testing::Property; using testing::Property;
using testing::_; using testing::_;
using ClangBackEnd::FilePath;
using ClangBackEnd::RequestSourceLocationsForRenamingMessage; using ClangBackEnd::RequestSourceLocationsForRenamingMessage;
using ClangBackEnd::RequestSourceRangesAndDiagnosticsForQueryMessage;
using ClangBackEnd::SourceLocationsContainer; using ClangBackEnd::SourceLocationsContainer;
using ClangBackEnd::SourceLocationsForRenamingMessage; using ClangBackEnd::SourceLocationsForRenamingMessage;
using ClangBackEnd::FilePath; using ClangBackEnd::SourceRangesAndDiagnosticsForQueryMessage;
using ClangBackEnd::SourceRangesContainer;
using ClangBackEnd::V2::FileContainer;
MATCHER_P2(IsSourceLocation, line, column, MATCHER_P2(IsSourceLocation, line, column,
std::string(negation ? "isn't" : "is") std::string(negation ? "isn't " : "is ")
+ ", line " + PrintToString(line) + "(" + PrintToString(line)
+ ", column " + PrintToString(column) + ", " + PrintToString(column)
+ ")"
) )
{ {
if (arg.line() != uint(line) return arg.line() == uint(line)
|| arg.column() != uint(column)) && arg.column() == uint(column);
return false;
return true;
} }
class RefactoringServer : public ::testing::Test class RefactoringServer : public ::testing::Test
@@ -77,22 +82,80 @@ TEST_F(RefactoringServer, RequestSourceLocationsForRenamingMessage)
"int v;\n\nint x = v + 3;\n", "int v;\n\nint x = v + 3;\n",
{"cc", "renamevariable.cpp"}, {"cc", "renamevariable.cpp"},
1}; 1};
SourceLocationsForRenamingMessage sourceLocationsForRenamingMessage;
EXPECT_CALL(mockRefactoringClient, EXPECT_CALL(mockRefactoringClient,
sourceLocationsForRenamingMessage( sourceLocationsForRenamingMessage(
AllOf(Property(&SourceLocationsForRenamingMessage::symbolName, "v"), AllOf(Property(&SourceLocationsForRenamingMessage::textDocumentRevision, 1),
Property(&SourceLocationsForRenamingMessage::symbolName, "v"),
Property(&SourceLocationsForRenamingMessage::sourceLocations, Property(&SourceLocationsForRenamingMessage::sourceLocations,
AllOf(Property(&SourceLocationsContainer::sourceLocationContainers, AllOf(Property(&SourceLocationsContainer::sourceLocationContainers,
AllOf(Contains(IsSourceLocation(1, 5)), AllOf(Contains(IsSourceLocation(1, 5)),
Contains(IsSourceLocation(3, 9)))), Contains(IsSourceLocation(3, 9)))),
Property(&SourceLocationsContainer::filePathsForTestOnly, Property(&SourceLocationsContainer::filePaths,
Contains(Pair(_, FilePath(TESTDATA_DIR, "renamevariable.cpp"))))))))) Contains(Pair(_, FilePath(TESTDATA_DIR, "renamevariable.cpp")))))))))
.Times(1); .Times(1);
refactoringServer.requestSourceLocationsForRenamingMessage(std::move(requestSourceLocationsForRenamingMessage)); refactoringServer.requestSourceLocationsForRenamingMessage(std::move(requestSourceLocationsForRenamingMessage));
} }
TEST_F(RefactoringServer, RequestSingleSourceRangesAndDiagnosticsForQueryMessage)
{
RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()",
{{{TESTDATA_DIR, "query_simplefunction.cpp"},
"void f()\n \t{}",
{"cc", "query_simplefunction.cpp"}}}};
EXPECT_CALL(mockRefactoringClient,
sourceRangesAndDiagnosticsForQueryMessage(
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
Property(&SourceRangesContainer::sourceRangeWithTextContainers,
Contains(IsSourceRangeWithText(1, 1, 2, 4, "void f() {}"))))))
.Times(1);
refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage));
}
TEST_F(RefactoringServer, RequestTwoSourceRangesAndDiagnosticsForQueryMessage)
{
RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()",
{{{TESTDATA_DIR, "query_simplefunction.cpp"},
"void f()\n \t{}",
{"cc", "query_simplefunction.cpp"}},
{{TESTDATA_DIR, "query_simplefunction.cpp"},
"void f()\n \t{}",
{"cc", "query_simplefunction.cpp"}}}};
EXPECT_CALL(mockRefactoringClient,
sourceRangesAndDiagnosticsForQueryMessage(
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
Property(&SourceRangesContainer::sourceRangeWithTextContainers,
Contains(IsSourceRangeWithText(1, 1, 2, 4, "void f() {}"))))))
.Times(2);
refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage));
}
TEST_F(RefactoringServer, RequestManySourceRangesAndDiagnosticsForQueryMessage)
{
std::vector<FileContainer> fileContainers;
std::fill_n(std::back_inserter(fileContainers),
std::thread::hardware_concurrency() + 3,
FileContainer{{TESTDATA_DIR, "query_simplefunction.cpp"},
"void f()\n \t{}",
{"cc", "query_simplefunction.cpp"}});
RequestSourceRangesAndDiagnosticsForQueryMessage requestSourceRangesAndDiagnosticsForQueryMessage{"functionDecl()",
std::move(fileContainers)};
EXPECT_CALL(mockRefactoringClient,
sourceRangesAndDiagnosticsForQueryMessage(
Property(&SourceRangesAndDiagnosticsForQueryMessage::sourceRanges,
Property(&SourceRangesContainer::sourceRangeWithTextContainers,
Contains(IsSourceRangeWithText(1, 1, 2, 4, "void f() {}"))))))
.Times(std::thread::hardware_concurrency() + 3);
refactoringServer.requestSourceRangesAndDiagnosticsForQueryMessage(std::move(requestSourceRangesAndDiagnosticsForQueryMessage));
}
void RefactoringServer::SetUp() void RefactoringServer::SetUp()
{ {
refactoringServer.setClient(&mockRefactoringClient); refactoringServer.setClient(&mockRefactoringClient);

View File

@@ -0,0 +1,67 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "googletest.h"
using testing::PrintToString;
namespace {
MATCHER_P4(IsSourceRange, startLine, startColumn, endLine, endColumn,
std::string(negation ? "isn't" : "is")
+ "[(" + PrintToString(startLine)
+ ", " + PrintToString(startColumn)
+ "), (" + PrintToString(endLine)
+ ", " + PrintToString(endColumn)
+ ")]"
)
{
return arg.start().line() == uint(startLine)
&& arg.start().column() == uint(startColumn)
&& arg.end().line() == uint(endLine)
&& arg.end().column() == uint(endColumn);
}
MATCHER_P5(IsSourceRangeWithText, startLine, startColumn, endLine, endColumn, text,
std::string(negation ? "isn't " : "is ")
+ "((" + PrintToString(startLine)
+ ", " + PrintToString(startColumn)
+ "), (" + PrintToString(endLine)
+ ", " + PrintToString(endColumn)
+ "), \"" + PrintToString(text)
+ "\")"
)
{
return arg.start().line() == uint(startLine)
&& arg.start().column() == uint(startColumn)
&& arg.end().line() == uint(endLine)
&& arg.end().column() == uint(endColumn)
&& arg.text() == text;
}
}

View File

@@ -42,7 +42,7 @@ namespace {
MATCHER_P2(IsSourceLocation, line, column, MATCHER_P2(IsSourceLocation, line, column,
std::string(negation ? "isn't" : "is") std::string(negation ? "isn't" : "is")
+ ", line " + PrintToString(line) + "line " + PrintToString(line)
+ ", column " + PrintToString(column) + ", column " + PrintToString(column)
) )
{ {

View File

@@ -93,6 +93,9 @@ SOURCES += \
!isEmpty(LIBTOOLING_LIBS) { !isEmpty(LIBTOOLING_LIBS) {
SOURCES += \ SOURCES += \
clangquery-test.cpp \
clangquerycurrentfilefindfilter-test.cpp \
clangqueryprojectfindfilter-test.cpp \
refactoringclientserverinprocess-test.cpp \ refactoringclientserverinprocess-test.cpp \
refactoringclient-test.cpp \ refactoringclient-test.cpp \
refactoringcompilationdatabase-test.cpp \ refactoringcompilationdatabase-test.cpp \
@@ -111,7 +114,12 @@ HEADERS += \
googletest.h \ googletest.h \
gtest-qt-printing.h \ gtest-qt-printing.h \
processevents-utilities.h \ processevents-utilities.h \
spydummy.h spydummy.h \
sourcerangecontainer-matcher.h \
dynamicastmatcherdiagnosticcontainer-matcher.h \
mocksearchresult.h \
mocksearch.h \
mocksearchhandle.h
!isEmpty(LIBCLANG_LIBS) { !isEmpty(LIBCLANG_LIBS) {
HEADERS += \ HEADERS += \