forked from qt-creator/qt-creator
ClangRefactoring: Improve follow symbol and usage
Change-Id: Idb42010443e4560489ef067e54d05b4e567598e9 Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -201,15 +201,14 @@ struct HighlightingTypes {
|
||||
MixinHighlightingTypes mixinHighlightingTypes;
|
||||
};
|
||||
|
||||
enum class SourceLocationKind : uchar
|
||||
{
|
||||
None = 0,
|
||||
enum class SourceLocationKind : uchar {
|
||||
Definition = 1,
|
||||
Declaration,
|
||||
DeclarationReference,
|
||||
Definition,
|
||||
MacroDefinition = 128,
|
||||
MacroUndefinition,
|
||||
MacroUsage,
|
||||
MacroUndefinition
|
||||
None = 255,
|
||||
};
|
||||
|
||||
enum class SymbolKind : uchar
|
||||
|
@@ -82,13 +82,15 @@ public:
|
||||
Sqlite::Table table;
|
||||
table.setUseIfNotExists(true);
|
||||
table.setName("locations");
|
||||
table.addColumn("symbolId", Sqlite::ColumnType::Integer);
|
||||
const Sqlite::Column &symbolIdColumn = table.addColumn("symbolId",
|
||||
Sqlite::ColumnType::Integer);
|
||||
const Sqlite::Column &lineColumn = table.addColumn("line", Sqlite::ColumnType::Integer);
|
||||
const Sqlite::Column &columnColumn = table.addColumn("column", Sqlite::ColumnType::Integer);
|
||||
const Sqlite::Column &sourceIdColumn = table.addColumn("sourceId", Sqlite::ColumnType::Integer);
|
||||
const Sqlite::Column &locationKindColumn = table.addColumn("locationKind", Sqlite::ColumnType::Integer);
|
||||
table.addUniqueIndex({sourceIdColumn, lineColumn, columnColumn});
|
||||
table.addIndex({sourceIdColumn, locationKindColumn});
|
||||
table.addIndex({symbolIdColumn});
|
||||
|
||||
table.initialize(database);
|
||||
}
|
||||
|
@@ -47,7 +47,20 @@ public:
|
||||
ReadStatement selectSourceUsagesForSymbolLocation{
|
||||
"SELECT directoryPath || '/' || sourceName, line, column "
|
||||
"FROM locations NATURAL JOIN sources NATURAL JOIN directories "
|
||||
"WHERE symbolId = (SELECT symbolId FROM locations WHERE sourceId=? AND line=? AND column=?)",
|
||||
"WHERE symbolId = (SELECT symbolId FROM locations WHERE sourceId=? AND line=? AND "
|
||||
"column=?)",
|
||||
database};
|
||||
ReadStatement selectSourceUsagesOrderedForSymbolLocation{
|
||||
"SELECT directoryPath || '/' || sourceName, line, column "
|
||||
"FROM locations NATURAL JOIN sources NATURAL JOIN directories "
|
||||
"WHERE symbolId = (SELECT symbolId FROM locations WHERE sourceId=? AND line=? AND "
|
||||
"column=?) ORDER BY locationKind LIMIT 2",
|
||||
database};
|
||||
ReadStatement selectSourceUsagesByLocationKindForSymbolLocation{
|
||||
"SELECT directoryPath || '/' || sourceName, line, column "
|
||||
"FROM locations NATURAL JOIN sources NATURAL JOIN directories "
|
||||
"WHERE symbolId = (SELECT symbolId FROM locations WHERE sourceId=? AND line=? AND "
|
||||
"column=?) AND locationKind = ?",
|
||||
database};
|
||||
ReadStatement selectSymbolsForKindAndStartsWith{
|
||||
"SELECT symbolId, symbolName, signature FROM symbols WHERE symbolKind = ? AND symbolName LIKE ?",
|
||||
|
@@ -68,7 +68,8 @@ void RefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &,
|
||||
|
||||
CppTools::Usages RefactoringEngine::locationsAt(const CppTools::CursorInEditor &data) const
|
||||
{
|
||||
CppTools::Usages usages;
|
||||
if (data.cursor().isNull())
|
||||
return {};
|
||||
|
||||
QTextCursor cursor = Utils::Text::wordStartCursor(data.cursor());
|
||||
Utils::OptionalLineColumn lineColumn = Utils::Text::convertPosition(cursor.document(),
|
||||
@@ -78,10 +79,30 @@ CppTools::Usages RefactoringEngine::locationsAt(const CppTools::CursorInEditor &
|
||||
const QByteArray filePath = data.filePath().toString().toUtf8();
|
||||
const ClangBackEnd::FilePathId filePathId = m_filePathCache.filePathId(ClangBackEnd::FilePathView(filePath));
|
||||
|
||||
usages = m_symbolQuery.sourceUsagesAt(filePathId, lineColumn->line, lineColumn->column);
|
||||
return m_symbolQuery.sourceUsagesAt(filePathId, lineColumn->line, lineColumn->column);
|
||||
}
|
||||
|
||||
return usages;
|
||||
return {};
|
||||
}
|
||||
|
||||
CppTools::Usages RefactoringEngine::declarationAt(const CppTools::CursorInEditor &data) const
|
||||
{
|
||||
if (data.cursor().isNull())
|
||||
return {};
|
||||
|
||||
QTextCursor cursor = Utils::Text::wordStartCursor(data.cursor());
|
||||
Utils::OptionalLineColumn lineColumn = Utils::Text::convertPosition(cursor.document(),
|
||||
cursor.position());
|
||||
|
||||
if (lineColumn) {
|
||||
const QByteArray filePath = data.filePath().toString().toUtf8();
|
||||
const ClangBackEnd::FilePathId filePathId = m_filePathCache.filePathId(
|
||||
ClangBackEnd::FilePathView(filePath));
|
||||
|
||||
return m_symbolQuery.declarationsAt(filePathId, lineColumn->line, lineColumn->column);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void RefactoringEngine::globalRename(const CppTools::CursorInEditor &data,
|
||||
@@ -104,16 +125,13 @@ void RefactoringEngine::globalFollowSymbol(const CppTools::CursorInEditor &data,
|
||||
CppTools::SymbolFinder *,
|
||||
bool) const
|
||||
{
|
||||
// TODO: replace that with specific followSymbol query
|
||||
const CppTools::Usages usages = locationsAt(data);
|
||||
const CppTools::Usages usages = declarationAt(data);
|
||||
CppTools::Usage usage = Utils::findOrDefault(usages, [&data](const CppTools::Usage &usage) {
|
||||
// We've already searched in the current file, skip it.
|
||||
if (usage.path == data.filePath().toString())
|
||||
return false;
|
||||
return true;
|
||||
return usage.path != data.filePath().toString();
|
||||
|
||||
});
|
||||
|
||||
processLinkCallback(Link(usage.path, usage.line, usage.column));
|
||||
processLinkCallback(Link(usage.path, usage.line, usage.column - 1));
|
||||
}
|
||||
|
||||
bool RefactoringEngine::isRefactoringEngineAvailable() const
|
||||
|
@@ -74,6 +74,7 @@ public:
|
||||
|
||||
private:
|
||||
CppTools::Usages locationsAt(const CppTools::CursorInEditor &data) const;
|
||||
CppTools::Usages declarationAt(const CppTools::CursorInEditor &data) const;
|
||||
|
||||
ClangBackEnd::RefactoringServerInterface &m_server;
|
||||
ClangBackEnd::RefactoringClientInterface &m_client;
|
||||
|
@@ -75,6 +75,36 @@ public:
|
||||
utf8Column);
|
||||
}
|
||||
|
||||
CppTools::Usages sourceUsagesAtByLocationKind(ClangBackEnd::FilePathId filePathId,
|
||||
int line,
|
||||
int utf8Column,
|
||||
ClangBackEnd::SourceLocationKind kind) const override
|
||||
{
|
||||
ReadStatement &locationsStatement = m_statementFactory.selectSourceUsagesByLocationKindForSymbolLocation;
|
||||
|
||||
const std::size_t reserveSize = 128;
|
||||
|
||||
return locationsStatement.template values<CppTools::Usage, 3>(reserveSize,
|
||||
filePathId.filePathId,
|
||||
line,
|
||||
utf8Column,
|
||||
int(kind));
|
||||
}
|
||||
|
||||
CppTools::Usages declarationsAt(ClangBackEnd::FilePathId filePathId,
|
||||
int line,
|
||||
int utf8Column) const override
|
||||
{
|
||||
ReadStatement &locationsStatement = m_statementFactory.selectSourceUsagesOrderedForSymbolLocation;
|
||||
|
||||
const std::size_t reserveSize = 128;
|
||||
|
||||
return locationsStatement.template values<CppTools::Usage, 3>(reserveSize,
|
||||
filePathId.filePathId,
|
||||
line,
|
||||
utf8Column);
|
||||
}
|
||||
|
||||
Symbols symbolsWithOneSymbolKinds(ClangBackEnd::SymbolKind symbolKind,
|
||||
Utils::SmallStringView searchTerm) const
|
||||
{
|
||||
|
@@ -46,10 +46,17 @@ public:
|
||||
virtual CppTools::Usages sourceUsagesAt(ClangBackEnd::FilePathId filePathId,
|
||||
int line,
|
||||
int utf8Column) const = 0;
|
||||
virtual CppTools::Usages sourceUsagesAtByLocationKind(ClangBackEnd::FilePathId filePathId,
|
||||
int line,
|
||||
int utf8Column,
|
||||
ClangBackEnd::SourceLocationKind) const = 0;
|
||||
virtual Symbols symbols(const ClangBackEnd::SymbolKinds &symbolKinds,
|
||||
Utils::SmallStringView searchTerm) const = 0;
|
||||
virtual Utils::optional<SourceLocation> locationForSymbolId(SymbolId symbolId,
|
||||
ClangBackEnd::SourceLocationKind kind) const = 0;
|
||||
virtual CppTools::Usages declarationsAt(ClangBackEnd::FilePathId filePathId,
|
||||
int line,
|
||||
int utf8Column) const = 0;
|
||||
|
||||
protected:
|
||||
~SymbolQueryInterface() = default;
|
||||
|
@@ -52,12 +52,12 @@ Utils::SmallString symbolName(const clang::NamedDecl *declaration)
|
||||
|
||||
SourceLocationKind sourceLocationKind(clang::index::SymbolRoleSet roles)
|
||||
{
|
||||
if (hasSymbolRole(clang::index::SymbolRole::Reference, roles))
|
||||
return SourceLocationKind::DeclarationReference;
|
||||
if (hasSymbolRole(clang::index::SymbolRole::Definition, roles))
|
||||
return SourceLocationKind::Definition;
|
||||
else if (hasSymbolRole(clang::index::SymbolRole::Declaration, roles))
|
||||
return SourceLocationKind::Declaration;
|
||||
else if (hasSymbolRole(clang::index::SymbolRole::Definition, roles))
|
||||
return SourceLocationKind::Definition;
|
||||
else if (hasSymbolRole(clang::index::SymbolRole::Reference, roles))
|
||||
return SourceLocationKind::DeclarationReference;
|
||||
|
||||
return SourceLocationKind::None;
|
||||
}
|
||||
|
14
tests/unit/unittest/data/symbolscollector/class.cpp
Normal file
14
tests/unit/unittest/data/symbolscollector/class.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
class Class
|
||||
{
|
||||
Class();
|
||||
Class(int);
|
||||
|
||||
void foo();
|
||||
|
||||
void bar() {}
|
||||
};
|
||||
|
||||
void Class::foo()
|
||||
{
|
||||
bar();
|
||||
}
|
@@ -453,11 +453,11 @@ TEST_F(FilePathCache, GetFileIdInAfterPopulateIfEmpty)
|
||||
TEST_F(FilePathCache, DontPopulateIfNotEmpty)
|
||||
{
|
||||
cacheNotFilled.filePathId("/path/to/file.cpp");
|
||||
|
||||
EXPECT_CALL(mockStorageFilled, fetchAllDirectories()).Times(0);
|
||||
EXPECT_CALL(mockStorageFilled, fetchAllSources()).Times(0);
|
||||
|
||||
cacheNotFilled.populateIfEmpty();
|
||||
|
||||
auto id = cacheNotFilled.filePathId("/path2/to/file.cpp");
|
||||
|
||||
ASSERT_FALSE(id.isValid());
|
||||
}
|
||||
|
||||
TEST_F(FilePathCache, GetDirectoryIdAfterPopulateIfEmpty)
|
||||
|
@@ -37,6 +37,9 @@
|
||||
#include <clangcodemodelservermessages.h>
|
||||
#include <clangpathwatcher.h>
|
||||
#include <clangrefactoringmessages.h>
|
||||
#include <coreplugin/find/searchresultitem.h>
|
||||
#include <coreplugin/locator/ilocatorfilter.h>
|
||||
#include <cpptools/usages.h>
|
||||
#include <filepath.h>
|
||||
#include <filepathcaching.h>
|
||||
#include <filepathview.h>
|
||||
@@ -46,6 +49,8 @@
|
||||
#include <pchpaths.h>
|
||||
#include <pchtask.h>
|
||||
#include <precompiledheadersupdatedmessage.h>
|
||||
#include <projectexplorer/headerpath.h>
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
#include <projectpartartefact.h>
|
||||
#include <projectpartentry.h>
|
||||
#include <projectpartpch.h>
|
||||
@@ -58,11 +63,7 @@
|
||||
#include <toolchainargumentscache.h>
|
||||
#include <tooltipinfo.h>
|
||||
#include <usedmacro.h>
|
||||
#include <cpptools/usages.h>
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
#include <projectexplorer/headerpath.h>
|
||||
#include <coreplugin/find/searchresultitem.h>
|
||||
#include <coreplugin/locator/ilocatorfilter.h>
|
||||
#include <utils/link.h>
|
||||
|
||||
namespace {
|
||||
ClangBackEnd::FilePathCaching *filePathCache = nullptr;
|
||||
@@ -178,6 +179,12 @@ std::ostream &operator<<(std::ostream &out, const LineColumn &lineColumn)
|
||||
return out << "(" << lineColumn.line << ", " << lineColumn.column << ")";
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const Link &link)
|
||||
{
|
||||
return out << "(" << link.targetFileName << ", " << link.targetLine << ", " << link.targetColumn
|
||||
<< ", " << link.linkTextStart << ", " << link.linkTextEnd << ")";
|
||||
}
|
||||
|
||||
const char * toText(Utils::Language language)
|
||||
{
|
||||
using Utils::Language;
|
||||
|
@@ -81,11 +81,13 @@ std::ostream &operator<<(std::ostream &out, const HeaderPath &headerPath);
|
||||
namespace Utils {
|
||||
class LineColumn;
|
||||
class SmallStringView;
|
||||
class Link;
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const LineColumn &lineColumn);
|
||||
std::ostream &operator<<(std::ostream &out, const Utils::Language &language);
|
||||
std::ostream &operator<<(std::ostream &out, const Utils::LanguageVersion &languageVersion);
|
||||
std::ostream &operator<<(std::ostream &out, const Utils::LanguageExtension &languageExtension);
|
||||
std::ostream &operator<<(std::ostream &out, const Link &link);
|
||||
|
||||
template <typename Type>
|
||||
std::ostream &operator<<(std::ostream &out, const Utils::optional<Type> &optional)
|
||||
|
@@ -46,6 +46,16 @@ MockSqliteReadStatement::values<CppTools::Usage, 3>(
|
||||
return valuesReturnSourceUsages(reserveSize, sourceId, line, column);
|
||||
}
|
||||
|
||||
template<>
|
||||
CppTools::Usages MockSqliteReadStatement::values<CppTools::Usage, 3>(std::size_t reserveSize,
|
||||
const int &sourceId,
|
||||
const int &line,
|
||||
const int &column,
|
||||
const int &locationKind)
|
||||
{
|
||||
return valuesReturnSourceUsages(reserveSize, sourceId, line, column, locationKind);
|
||||
}
|
||||
|
||||
template <>
|
||||
Symbols
|
||||
MockSqliteReadStatement::values<Symbol, 3>(
|
||||
|
@@ -78,8 +78,9 @@ public:
|
||||
MOCK_METHOD4(valuesReturnSourceLocations,
|
||||
SourceLocations(std::size_t, int, int, int));
|
||||
|
||||
MOCK_METHOD4(valuesReturnSourceUsages,
|
||||
CppTools::Usages(std::size_t, int, int, int));
|
||||
MOCK_METHOD4(valuesReturnSourceUsages, CppTools::Usages(std::size_t, int, int, int));
|
||||
|
||||
MOCK_METHOD5(valuesReturnSourceUsages, CppTools::Usages(std::size_t, int, int, int, int));
|
||||
|
||||
MOCK_METHOD1(valuesReturnStdVectorDirectory,
|
||||
std::vector<Sources::Directory>(std::size_t));
|
||||
@@ -191,6 +192,13 @@ MockSqliteReadStatement::values<CppTools::Usage, 3>(
|
||||
const int &line,
|
||||
const int &column);
|
||||
|
||||
template<>
|
||||
CppTools::Usages MockSqliteReadStatement::values<CppTools::Usage, 3>(std::size_t reserveSize,
|
||||
const int &sourceId,
|
||||
const int &line,
|
||||
const int &column,
|
||||
const int &locationKind);
|
||||
|
||||
template <>
|
||||
Symbols
|
||||
MockSqliteReadStatement::values<Symbol, 3>(
|
||||
|
@@ -40,4 +40,11 @@ public:
|
||||
ClangRefactoring::Symbols(const ClangBackEnd::SymbolKinds &symbolKinds, Utils::SmallStringView searchTerm));
|
||||
MOCK_CONST_METHOD2(locationForSymbolId,
|
||||
Utils::optional<ClangRefactoring::SourceLocation>(ClangRefactoring::SymbolId symbolId, ClangBackEnd::SourceLocationKind kind));
|
||||
MOCK_CONST_METHOD4(sourceUsagesAtByLocationKind,
|
||||
CppTools::Usages(ClangBackEnd::FilePathId filePathId,
|
||||
int line,
|
||||
int utf8Column,
|
||||
ClangBackEnd::SourceLocationKind));
|
||||
MOCK_CONST_METHOD3(declarationsAt,
|
||||
CppTools::Usages(ClangBackEnd::FilePathId filePathId, int line, int utf8Column));
|
||||
};
|
||||
|
@@ -60,7 +60,9 @@ TEST_F(RefactoringDatabaseInitializer, AddLocationsTable)
|
||||
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS locations(symbolId INTEGER, line INTEGER, column INTEGER, sourceId INTEGER, locationKind INTEGER)")));
|
||||
EXPECT_CALL(mockDatabase, execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_locations_sourceId_line_column ON locations(sourceId, line, column)")));
|
||||
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId_locationKind ON locations(sourceId, locationKind)")));
|
||||
|
||||
EXPECT_CALL(mockDatabase,
|
||||
execute(Eq(
|
||||
"CREATE INDEX IF NOT EXISTS index_locations_symbolId ON locations(symbolId)")));
|
||||
initializer.createLocationsTable();
|
||||
}
|
||||
|
||||
@@ -220,6 +222,9 @@ TEST_F(RefactoringDatabaseInitializer, CreateInTheContructor)
|
||||
EXPECT_CALL(mockDatabase,
|
||||
execute(Eq("CREATE INDEX IF NOT EXISTS index_locations_sourceId_locationKind ON "
|
||||
"locations(sourceId, locationKind)")));
|
||||
EXPECT_CALL(mockDatabase,
|
||||
execute(Eq(
|
||||
"CREATE INDEX IF NOT EXISTS index_locations_symbolId ON locations(symbolId)")));
|
||||
EXPECT_CALL(mockDatabase,
|
||||
execute(Eq("CREATE TABLE IF NOT EXISTS sources(sourceId INTEGER PRIMARY KEY, "
|
||||
"directoryId INTEGER, sourceName TEXT)")));
|
||||
|
@@ -65,13 +65,15 @@ protected:
|
||||
commandLine = Utils::SmallStringVector(
|
||||
optionsBuilder.build(projectFile.kind, CppTools::UsePrecompiledHeaders::No));
|
||||
commandLine.push_back(qStringFilePath);
|
||||
ON_CALL(mockFilePathCaching, filePathId(Eq(clangBackEndFilePath))).WillByDefault(Return(12));
|
||||
cursor.setPosition(11);
|
||||
}
|
||||
|
||||
protected:
|
||||
NiceMock<MockFilePathCaching> mockFilePathCaching;
|
||||
MockRefactoringServer mockRefactoringServer;
|
||||
MockRefactoringClient mockRefactoringClient;
|
||||
MockSymbolQuery mockSymbolQuery;
|
||||
NiceMock<MockSymbolQuery> mockSymbolQuery;
|
||||
ClangRefactoring::RefactoringEngine engine{mockRefactoringServer,
|
||||
mockRefactoringClient,
|
||||
mockFilePathCaching,
|
||||
@@ -85,27 +87,96 @@ protected:
|
||||
SmallStringVector commandLine;
|
||||
ProjectExplorer::Project project;
|
||||
CppTools::ProjectPart::Ptr projectPart;
|
||||
CppTools::Usages usages{{"/path1", 1, 3}, {"/path2", 4, 5}};
|
||||
CppTools::ProjectFile projectFile{qStringFilePath, CppTools::ProjectFile::CXXSource};
|
||||
};
|
||||
|
||||
TEST_F(RefactoringEngine, ExpectSourceUsagesAtInFindUsages)
|
||||
TEST_F(RefactoringEngine, FindUsages)
|
||||
{
|
||||
cursor.setPosition(11);
|
||||
ON_CALL(mockSymbolQuery, sourceUsagesAt(Eq(12), 2, 5)).WillByDefault(Return(usages));
|
||||
NiceMock<MockFunction<void(const CppTools::Usages &)>> mockCallback;
|
||||
|
||||
EXPECT_CALL(mockSymbolQuery, sourceUsagesAt(_, 2, 5));
|
||||
EXPECT_CALL(mockCallback, Call(usages));
|
||||
|
||||
engine.findUsages(CppTools::CursorInEditor{cursor, filePath},
|
||||
[](const CppTools::Usages &) {});
|
||||
engine.findUsages(CppTools::CursorInEditor{cursor, filePath}, mockCallback.AsStdFunction());
|
||||
}
|
||||
|
||||
TEST_F(RefactoringEngine, ExpectSourceUsagesAtInGlobalRename)
|
||||
TEST_F(RefactoringEngine, CallFindUsages)
|
||||
{
|
||||
cursor.setPosition(11);
|
||||
EXPECT_CALL(mockSymbolQuery, sourceUsagesAt(Eq(12), 2, 5));
|
||||
|
||||
EXPECT_CALL(mockSymbolQuery, sourceUsagesAt(_, 2, 5));
|
||||
engine.findUsages(CppTools::CursorInEditor{cursor, filePath}, [](const CppTools::Usages &) {});
|
||||
}
|
||||
|
||||
TEST_F(RefactoringEngine, FindUsagesWithInvalidCursor)
|
||||
{
|
||||
EXPECT_CALL(mockSymbolQuery, sourceUsagesAt(_, _, _)).Times(0);
|
||||
|
||||
engine.findUsages(CppTools::CursorInEditor{{}, filePath}, [](const CppTools::Usages &) {});
|
||||
}
|
||||
|
||||
TEST_F(RefactoringEngine, CallSourceUsagesInInGlobalRename)
|
||||
{
|
||||
EXPECT_CALL(mockSymbolQuery, sourceUsagesAt(Eq(12), 2, 5));
|
||||
|
||||
engine.globalRename(CppTools::CursorInEditor{cursor, filePath},
|
||||
[](const CppTools::Usages &) {}, QString());
|
||||
[](const CppTools::Usages &) {},
|
||||
{});
|
||||
}
|
||||
|
||||
TEST_F(RefactoringEngine, CallSourceUsagesInInGlobalRenameWithInvalidCursor)
|
||||
{
|
||||
EXPECT_CALL(mockSymbolQuery, sourceUsagesAt(_, _, _)).Times(0);
|
||||
|
||||
engine.globalRename(CppTools::CursorInEditor{{}, filePath}, [](const CppTools::Usages &) {}, {});
|
||||
}
|
||||
|
||||
TEST_F(RefactoringEngine, CallDeclarationsAtInInGlobalFollowSymbol)
|
||||
{
|
||||
|
||||
EXPECT_CALL(mockSymbolQuery, declarationsAt(Eq(12), 2, 5));
|
||||
|
||||
engine.globalFollowSymbol(
|
||||
CppTools::CursorInEditor{cursor, filePath}, [](const Utils::Link &) {}, {}, {}, {}, {});
|
||||
}
|
||||
|
||||
TEST_F(RefactoringEngine, CallDeclarationsAtInInGlobalFollowSymbolWithInvalidCursor)
|
||||
{
|
||||
EXPECT_CALL(mockSymbolQuery, declarationsAt(_, _, _)).Times(0);
|
||||
|
||||
engine.globalFollowSymbol(
|
||||
CppTools::CursorInEditor{{}, filePath}, [](const Utils::Link &) {}, {}, {}, {}, {});
|
||||
}
|
||||
|
||||
TEST_F(RefactoringEngine, InGlobalFollowSymbol)
|
||||
{
|
||||
using Utils::Link;
|
||||
NiceMock<MockFunction<void(const Link &)>> mockCallback;
|
||||
ON_CALL(mockSymbolQuery, declarationsAt(Eq(12), 2, 5)).WillByDefault(Return(usages));
|
||||
|
||||
EXPECT_CALL(mockCallback,
|
||||
Call(AllOf(Field(&Link::targetFileName, Eq("/path1")),
|
||||
Field(&Link::targetLine, Eq(1)),
|
||||
Field(&Link::targetColumn, Eq(2)))));
|
||||
|
||||
engine.globalFollowSymbol(
|
||||
CppTools::CursorInEditor{cursor, filePath}, mockCallback.AsStdFunction(), {}, {}, {}, {});
|
||||
}
|
||||
|
||||
TEST_F(RefactoringEngine, InGlobalFollowSymbolSkipCurrentFile)
|
||||
{
|
||||
using Utils::Link;
|
||||
NiceMock<MockFunction<void(const Link &)>> mockCallback;
|
||||
CppTools::Usages usages{{clangBackEndFilePath, 1, 3}, {"/path2", 4, 5}};
|
||||
ON_CALL(mockSymbolQuery, declarationsAt(Eq(12), 2, 5)).WillByDefault(Return(usages));
|
||||
|
||||
EXPECT_CALL(mockCallback,
|
||||
Call(AllOf(Field(&Link::targetFileName, Eq("/path2")),
|
||||
Field(&Link::targetLine, Eq(4)),
|
||||
Field(&Link::targetColumn, Eq(4)))));
|
||||
|
||||
engine.globalFollowSymbol(
|
||||
CppTools::CursorInEditor{cursor, filePath}, mockCallback.AsStdFunction(), {}, {}, {}, {});
|
||||
}
|
||||
|
||||
TEST_F(RefactoringEngine, EngineIsNotUsableForUnusableServer)
|
||||
|
@@ -61,12 +61,11 @@ protected:
|
||||
MockSqliteReadStatement &selectSymbolsForKindAndStartsWith2 = mockStatementFactory.selectSymbolsForKindAndStartsWith2;
|
||||
MockSqliteReadStatement &selectSymbolsForKindAndStartsWith3 = mockStatementFactory.selectSymbolsForKindAndStartsWith3;
|
||||
MockSqliteReadStatement &selectLocationOfSymbol = mockStatementFactory.selectLocationOfSymbol;
|
||||
SourceLocations locations{{1, 1, 1},
|
||||
{1, 2, 3},
|
||||
{2, 1, 1},
|
||||
{2, 3, 1},
|
||||
{4, 1, 1},
|
||||
{4, 1, 3}};
|
||||
MockSqliteReadStatement &selectSourceUsagesOrderedForSymbolLocation = mockStatementFactory
|
||||
.selectSourceUsagesOrderedForSymbolLocation;
|
||||
MockSqliteReadStatement &selectSourceUsagesByLocationKindForSymbolLocation
|
||||
= mockStatementFactory.selectSourceUsagesByLocationKindForSymbolLocation;
|
||||
SourceLocations locations{{1, 1, 1}, {1, 2, 3}, {2, 1, 1}, {2, 3, 1}, {4, 1, 1}, {4, 1, 3}};
|
||||
MockQuery query{mockStatementFactory};
|
||||
};
|
||||
|
||||
@@ -78,8 +77,9 @@ protected:
|
||||
database.execute("INSERT INTO sources VALUES (1, 1, \"filename.h\")");
|
||||
database.execute("INSERT INTO sources VALUES (2, 1, \"filename.cpp\")");
|
||||
database.execute("INSERT INTO directories VALUES (1, \"/path/to\")");
|
||||
database.execute("INSERT INTO locations VALUES (1, 2, 3, 1, 1)");
|
||||
database.execute("INSERT INTO locations VALUES (1, 4, 6, 2, 3)");
|
||||
database.execute("INSERT INTO locations VALUES (1, 2, 3, 1, 2)");
|
||||
database.execute("INSERT INTO locations VALUES (1, 4, 6, 2, 1)");
|
||||
database.execute("INSERT INTO locations VALUES (1, 20, 36, 2, 3)");
|
||||
database.execute("INSERT INTO symbols VALUES (1, \"functionusr\", \"Function\", 3, \"void function(int)\")");
|
||||
database.execute("INSERT INTO symbols VALUES (2, \"classusr\", \"Class\", 2, \"class Class final\")");
|
||||
database.execute("INSERT INTO symbols VALUES (3, \"enumusr\", \"Enum\", 1, \"enum Enum : char\")");
|
||||
@@ -105,7 +105,8 @@ TEST_F(SymbolQuerySlowTest, LocationsAt)
|
||||
|
||||
ASSERT_THAT(locations,
|
||||
UnorderedElementsAre(SourceLocation(1, 2, 3),
|
||||
SourceLocation(2, 4, 6)));
|
||||
SourceLocation(2, 4, 6),
|
||||
SourceLocation(2, 20, 36)));
|
||||
}
|
||||
|
||||
TEST_F(SymbolQuery, SourceUsagesAtCallsValues)
|
||||
@@ -121,7 +122,8 @@ TEST_F(SymbolQuerySlowTest, SourceUsagesAt)
|
||||
|
||||
ASSERT_THAT(usages,
|
||||
UnorderedElementsAre(CppTools::Usage("/path/to/filename.h", 2, 3),
|
||||
CppTools::Usage("/path/to/filename.cpp", 4, 6)));
|
||||
CppTools::Usage("/path/to/filename.cpp", 4, 6),
|
||||
CppTools::Usage("/path/to/filename.cpp", 20, 36)));
|
||||
}
|
||||
|
||||
TEST_F(SymbolQuery, SymbolsCallsValuesWithOneKindParameter)
|
||||
@@ -193,4 +195,39 @@ TEST_F(SymbolQuerySlowTest, LocationForSymbolId)
|
||||
ASSERT_THAT(location.value(), Eq(SourceLocation(2, {4, 6})));
|
||||
}
|
||||
|
||||
TEST_F(SymbolQuery, SourceUsagesAtByLocationKindCallsValues)
|
||||
{
|
||||
EXPECT_CALL(selectSourceUsagesByLocationKindForSymbolLocation,
|
||||
valuesReturnSourceUsages(
|
||||
_, 42, 14, 7, static_cast<int>(ClangBackEnd::SourceLocationKind::Definition)));
|
||||
|
||||
query.sourceUsagesAtByLocationKind(42, 14, 7, ClangBackEnd::SourceLocationKind::Definition);
|
||||
}
|
||||
|
||||
TEST_F(SymbolQuerySlowTest, SourceUsagesAtByLocationKind)
|
||||
{
|
||||
auto usages = query.sourceUsagesAtByLocationKind(2,
|
||||
4,
|
||||
6,
|
||||
ClangBackEnd::SourceLocationKind::Definition);
|
||||
|
||||
ASSERT_THAT(usages, ElementsAre(CppTools::Usage("/path/to/filename.cpp", 4, 6)));
|
||||
}
|
||||
|
||||
TEST_F(SymbolQuery, DeclarationsAtCallsValues)
|
||||
{
|
||||
EXPECT_CALL(selectSourceUsagesOrderedForSymbolLocation, valuesReturnSourceUsages(_, 42, 14, 7));
|
||||
|
||||
query.declarationsAt(42, 14, 7);
|
||||
}
|
||||
|
||||
TEST_F(SymbolQuerySlowTest, DeclarationsAt)
|
||||
{
|
||||
auto usages = query.declarationsAt(2, 4, 6);
|
||||
|
||||
ASSERT_THAT(usages,
|
||||
ElementsAre(CppTools::Usage("/path/to/filename.cpp", 4, 6),
|
||||
CppTools::Usage("/path/to/filename.h", 2, 3)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@@ -648,4 +648,44 @@ TEST_F(SymbolsCollector, ClearInputFilesAfterCollectingSymbols)
|
||||
|
||||
ASSERT_TRUE(collector.isClean());
|
||||
}
|
||||
|
||||
TEST_F(SymbolsCollector, ClassDeclarations)
|
||||
{
|
||||
collector.setFile(filePathId(TESTDATA_DIR "/symbolscollector/class.cpp"), {"cc"});
|
||||
|
||||
collector.collectSymbols();
|
||||
|
||||
ASSERT_THAT(
|
||||
collector.sourceLocations(),
|
||||
AllOf(Contains(IsSourceLocationEntry(symbolId("Class"),
|
||||
filePathId(TESTDATA_DIR "/symbolscollector/class.cpp"),
|
||||
1,
|
||||
7,
|
||||
SourceLocationKind::Definition)),
|
||||
Contains(IsSourceLocationEntry(symbolId("bar"),
|
||||
filePathId(TESTDATA_DIR "/symbolscollector/class.cpp"),
|
||||
8,
|
||||
8,
|
||||
SourceLocationKind::Definition)),
|
||||
Contains(IsSourceLocationEntry(symbolId("foo"),
|
||||
filePathId(TESTDATA_DIR "/symbolscollector/class.cpp"),
|
||||
11,
|
||||
13,
|
||||
SourceLocationKind::Definition)),
|
||||
Contains(IsSourceLocationEntry(symbolId("foo"),
|
||||
filePathId(TESTDATA_DIR "/symbolscollector/class.cpp"),
|
||||
6,
|
||||
8,
|
||||
SourceLocationKind::Declaration)),
|
||||
Contains(IsSourceLocationEntry(symbolId("Class"),
|
||||
filePathId(TESTDATA_DIR "/symbolscollector/class.cpp"),
|
||||
11,
|
||||
6,
|
||||
SourceLocationKind::DeclarationReference)),
|
||||
Contains(IsSourceLocationEntry(symbolId("bar"),
|
||||
filePathId(TESTDATA_DIR "/symbolscollector/class.cpp"),
|
||||
13,
|
||||
5,
|
||||
SourceLocationKind::DeclarationReference))));
|
||||
}
|
||||
} // namespace
|
||||
|
Reference in New Issue
Block a user