forked from qt-creator/qt-creator
Clang: Add usage functions to symbol query
Change-Id: If68a5119c863e616fea40275136d028abcf441f3 Reviewed-by: Jake Petroules <jake.petroules@qt.io> Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -44,6 +44,11 @@ public:
|
|||||||
" (SELECT symbolId FROM locations WHERE sourceId=? AND line=? AND column=?) "
|
" (SELECT symbolId FROM locations WHERE sourceId=? AND line=? AND column=?) "
|
||||||
"ORDER BY sourceId, line, column",
|
"ORDER BY sourceId, line, column",
|
||||||
database};
|
database};
|
||||||
|
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=?)",
|
||||||
|
database};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ClangRefactoring
|
} // namespace ClangRefactoring
|
||||||
|
|||||||
@@ -43,6 +43,14 @@ public:
|
|||||||
: filePathId{directoryId, sourceId}, line(line), column(column)
|
: filePathId{directoryId, sourceId}, line(line), column(column)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
friend bool operator==(SourceLocation first, SourceLocation second)
|
||||||
|
{
|
||||||
|
return first.filePathId == second.filePathId
|
||||||
|
&& first.line == second.line
|
||||||
|
&& first.column == second.column;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
ClangBackEnd::FilePathId filePathId;
|
ClangBackEnd::FilePathId filePathId;
|
||||||
int line;
|
int line;
|
||||||
int column;
|
int column;
|
||||||
|
|||||||
@@ -30,6 +30,8 @@
|
|||||||
#include <filepathid.h>
|
#include <filepathid.h>
|
||||||
#include <sourcelocations.h>
|
#include <sourcelocations.h>
|
||||||
|
|
||||||
|
#include <cpptools/usages.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace ClangRefactoring {
|
namespace ClangRefactoring {
|
||||||
@@ -56,6 +58,18 @@ public:
|
|||||||
utf8Column);
|
utf8Column);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CppTools::Usages sourceUsagesAt(ClangBackEnd::FilePathId filePathId, int line, int utf8Column)
|
||||||
|
{
|
||||||
|
ReadStatement &locationsStatement = m_statementFactory.selectSourceUsagesForSymbolLocation;
|
||||||
|
|
||||||
|
const std::size_t reserveSize = 128;
|
||||||
|
|
||||||
|
return locationsStatement.template values<CppTools::Usage, 3>(reserveSize,
|
||||||
|
filePathId.fileNameId,
|
||||||
|
line,
|
||||||
|
utf8Column);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StatementFactory &m_statementFactory;
|
StatementFactory &m_statementFactory;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2017 The Qt Company Ltd.
|
** Copyright (C) 2016 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of Qt Creator.
|
** This file is part of Qt Creator.
|
||||||
@@ -23,32 +23,40 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include "googletest.h"
|
#pragma once
|
||||||
|
|
||||||
#include "mocksqlitedatabase.h"
|
#include <utils/smallstringview.h>
|
||||||
#include "mocksqlitereadstatement.h"
|
|
||||||
#include "mocksqlitewritestatement.h"
|
|
||||||
|
|
||||||
#include <querysqlitestatementfactory.h>
|
#include <QString>
|
||||||
|
|
||||||
namespace {
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
using StatementFactory = ClangRefactoring::QuerySqliteStatementFactory<MockSqliteDatabase,
|
namespace CppTools {
|
||||||
MockSqliteReadStatement>;
|
|
||||||
|
|
||||||
class QuerySqliteStatementFactory : public testing::Test
|
class Usage
|
||||||
{
|
{
|
||||||
protected:
|
public:
|
||||||
MockSqliteDatabase mockDatabase;
|
Usage(Utils::SmallStringView path, int line, int column)
|
||||||
StatementFactory factory{mockDatabase};
|
: path(QString::fromUtf8(path.data(), int(path.size()))),
|
||||||
|
line(line),
|
||||||
|
column(column)
|
||||||
|
{}
|
||||||
|
|
||||||
|
friend bool operator==(const Usage &first, const Usage &second)
|
||||||
|
{
|
||||||
|
return first.line == second.line
|
||||||
|
&& first.column == second.column
|
||||||
|
&& first.path == second.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
QString path;
|
||||||
|
int line;
|
||||||
|
int column;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(QuerySqliteStatementFactory, SelectLocationsForSymbolLocation)
|
using Usages = std::vector<Usage>;
|
||||||
{
|
using UsagesCallback = std::function<void(const Usages &usages)>;
|
||||||
ASSERT_THAT(factory.selectLocationsForSymbolLocation.sqlStatement,
|
|
||||||
"SELECT directoryId, sourceId, line, column FROM locations JOIN sources USING(sourceId) WHERE symbolId = "
|
|
||||||
" (SELECT symbolId FROM locations WHERE sourceId=? AND line=? AND column=?) "
|
|
||||||
"ORDER BY sourceId, line, column");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
} // namespace CppTools
|
||||||
@@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
#include "gtest-creator-printing.h"
|
#include "gtest-creator-printing.h"
|
||||||
|
|
||||||
|
#include "gtest-qt-printing.h"
|
||||||
|
|
||||||
#include <gtest/gtest-printers.h>
|
#include <gtest/gtest-printers.h>
|
||||||
|
|
||||||
#include <sourcelocations.h>
|
#include <sourcelocations.h>
|
||||||
@@ -32,11 +34,12 @@
|
|||||||
#include <sourcelocationentry.h>
|
#include <sourcelocationentry.h>
|
||||||
#include <clangpathwatcher.h>
|
#include <clangpathwatcher.h>
|
||||||
|
|
||||||
|
#include <cpptools/usages.h>
|
||||||
|
|
||||||
#include <projectexplorer/projectmacro.h>
|
#include <projectexplorer/projectmacro.h>
|
||||||
|
|
||||||
#include <coreplugin/find/searchresultitem.h>
|
#include <coreplugin/find/searchresultitem.h>
|
||||||
|
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
namespace Search {
|
namespace Search {
|
||||||
|
|
||||||
@@ -157,3 +160,13 @@ std::ostream &operator<<(std::ostream &out, const SourceLocation &location)
|
|||||||
return out << "(" << location.filePathId << ", " << location.line << ", " << location.column << ")";
|
return out << "(" << location.filePathId << ", " << location.line << ", " << location.column << ")";
|
||||||
}
|
}
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
||||||
|
|
||||||
|
|
||||||
|
namespace CppTools {
|
||||||
|
class Usage;
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &out, const Usage &usage)
|
||||||
|
{
|
||||||
|
return out << "(" << usage.path << ", " << usage.line << ", " << usage.column <<")";
|
||||||
|
}
|
||||||
|
} // namespace CppTools
|
||||||
|
|||||||
@@ -78,3 +78,10 @@ class SourceLocation;
|
|||||||
|
|
||||||
std::ostream &operator<<(std::ostream &out, const SourceLocation &location);
|
std::ostream &operator<<(std::ostream &out, const SourceLocation &location);
|
||||||
} // namespace ClangRefactoring
|
} // namespace ClangRefactoring
|
||||||
|
|
||||||
|
|
||||||
|
namespace CppTools {
|
||||||
|
class Usage;
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &out, const Usage &usage);
|
||||||
|
} // namespace CppTools
|
||||||
|
|||||||
@@ -35,6 +35,17 @@ MockSqliteReadStatement::values<SourceLocation, 4>(std::size_t reserveSize,
|
|||||||
return valuesReturnSourceLocations(reserveSize, sourceId, line, column);
|
return valuesReturnSourceLocations(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)
|
||||||
|
{
|
||||||
|
return valuesReturnSourceUsages(reserveSize, sourceId, line, column);
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::vector<Sources::Directory> MockSqliteReadStatement::values<Sources::Directory, 2>(std::size_t reserveSize)
|
std::vector<Sources::Directory> MockSqliteReadStatement::values<Sources::Directory, 2>(std::size_t reserveSize)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,6 +32,8 @@
|
|||||||
#include <filepathstoragesources.h>
|
#include <filepathstoragesources.h>
|
||||||
#include <stringcachefwd.h>
|
#include <stringcachefwd.h>
|
||||||
|
|
||||||
|
#include <cpptools/usages.h>
|
||||||
|
|
||||||
#include <utils/optional.h>
|
#include <utils/optional.h>
|
||||||
#include <utils/smallstring.h>
|
#include <utils/smallstring.h>
|
||||||
|
|
||||||
@@ -55,6 +57,9 @@ public:
|
|||||||
MOCK_METHOD4(valuesReturnSourceLocations,
|
MOCK_METHOD4(valuesReturnSourceLocations,
|
||||||
SourceLocations(std::size_t, int, int, int));
|
SourceLocations(std::size_t, int, int, int));
|
||||||
|
|
||||||
|
MOCK_METHOD4(valuesReturnSourceUsages,
|
||||||
|
CppTools::Usages(std::size_t, int, int, int));
|
||||||
|
|
||||||
MOCK_METHOD1(valuesReturnStdVectorDirectory,
|
MOCK_METHOD1(valuesReturnStdVectorDirectory,
|
||||||
std::vector<Sources::Directory>(std::size_t));
|
std::vector<Sources::Directory>(std::size_t));
|
||||||
|
|
||||||
@@ -106,6 +111,13 @@ MockSqliteReadStatement::values<SourceLocation, 4>(
|
|||||||
const int &line,
|
const int &line,
|
||||||
const int &column);
|
const int &column);
|
||||||
|
|
||||||
|
template <>
|
||||||
|
CppTools::Usages
|
||||||
|
MockSqliteReadStatement::values<CppTools::Usage, 3>(
|
||||||
|
std::size_t reserveSize,
|
||||||
|
const int &sourceId,
|
||||||
|
const int &line,
|
||||||
|
const int &column);
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
std::vector<Sources::Directory> MockSqliteReadStatement::values<Sources::Directory, 2>(std::size_t reserveSize);
|
std::vector<Sources::Directory> MockSqliteReadStatement::values<Sources::Directory, 2>(std::size_t reserveSize);
|
||||||
|
|||||||
@@ -28,10 +28,13 @@
|
|||||||
#include "mocksqlitedatabase.h"
|
#include "mocksqlitedatabase.h"
|
||||||
#include "mocksqlitereadstatement.h"
|
#include "mocksqlitereadstatement.h"
|
||||||
|
|
||||||
#include <symbolquery.h>
|
|
||||||
#include <querysqlitestatementfactory.h>
|
#include <querysqlitestatementfactory.h>
|
||||||
|
#include <refactoringdatabaseinitializer.h>
|
||||||
|
#include <symbolquery.h>
|
||||||
|
|
||||||
#include <sqlitedatabase.h>
|
#include <sqlitedatabase.h>
|
||||||
|
#include <sqlitereadstatement.h>
|
||||||
|
#include <sqlitewritestatement.h>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -42,13 +45,48 @@ using StatementFactory = QuerySqliteStatementFactory<MockSqliteDatabase,
|
|||||||
MockSqliteReadStatement>;
|
MockSqliteReadStatement>;
|
||||||
using Query = ClangRefactoring::SymbolQuery<StatementFactory>;
|
using Query = ClangRefactoring::SymbolQuery<StatementFactory>;
|
||||||
|
|
||||||
|
struct Data
|
||||||
|
{
|
||||||
|
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
|
||||||
|
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> initializer{database};
|
||||||
|
using StatementFactory = QuerySqliteStatementFactory<Sqlite::Database,
|
||||||
|
Sqlite::ReadStatement>;
|
||||||
|
using Query = ClangRefactoring::SymbolQuery<StatementFactory>;
|
||||||
|
StatementFactory statementFactory{database};
|
||||||
|
Query query{statementFactory};
|
||||||
|
};
|
||||||
|
|
||||||
class SymbolQuery : public testing::Test
|
class SymbolQuery : public testing::Test
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
static void SetUpTestCase()
|
||||||
|
{
|
||||||
|
data = std::make_unique<Data>();
|
||||||
|
insertDataInDatabase();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TearDownTestCase()
|
||||||
|
{
|
||||||
|
data.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void insertDataInDatabase()
|
||||||
|
{
|
||||||
|
auto &database = data->database;
|
||||||
|
database.execute("INSERT INTO sources VALUES (1, 1, \"filename.h\", 1)");
|
||||||
|
database.execute("INSERT INTO sources VALUES (2, 1, \"filename.cpp\", 1)");
|
||||||
|
database.execute("INSERT INTO directories VALUES (1, \"/path/to\")");
|
||||||
|
database.execute("INSERT INTO locations VALUES (1, 2, 3, 1)");
|
||||||
|
database.execute("INSERT INTO locations VALUES (1, 4, 6, 2)");
|
||||||
|
database.execute("INSERT INTO symbols VALUES (1, \"functionusr\", \"function\")");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static std::unique_ptr<Data> data;
|
||||||
NiceMock<MockSqliteDatabase> mockDatabase;
|
NiceMock<MockSqliteDatabase> mockDatabase;
|
||||||
StatementFactory statementFactory{mockDatabase};
|
StatementFactory statementFactory{mockDatabase};
|
||||||
MockSqliteReadStatement &selectLocationsForSymbolLocation = statementFactory.selectLocationsForSymbolLocation;
|
MockSqliteReadStatement &selectLocationsForSymbolLocation = statementFactory.selectLocationsForSymbolLocation;
|
||||||
|
MockSqliteReadStatement &selectSourceUsagesForSymbolLocation = statementFactory.selectSourceUsagesForSymbolLocation;
|
||||||
SourceLocations locations{{{1, 1}, 1, 1},
|
SourceLocations locations{{{1, 1}, 1, 1},
|
||||||
{{1, 1}, 2, 3},
|
{{1, 1}, 2, 3},
|
||||||
{{1, 2}, 1, 1},
|
{{1, 2}, 1, 1},
|
||||||
@@ -56,14 +94,41 @@ protected:
|
|||||||
{{1, 4}, 1, 1},
|
{{1, 4}, 1, 1},
|
||||||
{{1, 4}, 1, 3}};
|
{{1, 4}, 1, 3}};
|
||||||
Query query{statementFactory};
|
Query query{statementFactory};
|
||||||
|
Data::Query &realQuery = data->query;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(SymbolQuery, LocationsAt)
|
std::unique_ptr<Data> SymbolQuery::data;
|
||||||
|
|
||||||
|
TEST_F(SymbolQuery, LocationsAtCallsValues)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(selectLocationsForSymbolLocation, valuesReturnSourceLocations(_, 42, 14, 7))
|
EXPECT_CALL(selectLocationsForSymbolLocation, valuesReturnSourceLocations(_, 42, 14, 7));
|
||||||
.WillRepeatedly(Return(locations));
|
|
||||||
|
|
||||||
query.locationsAt({1, 42}, 14, 7);
|
query.locationsAt({1, 42}, 14, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(SymbolQuery, LocationsAt)
|
||||||
|
{
|
||||||
|
auto locations = realQuery.locationsAt({1, 2}, 4, 6);
|
||||||
|
|
||||||
|
ASSERT_THAT(locations,
|
||||||
|
UnorderedElementsAre(SourceLocation({1, 1}, 2, 3),
|
||||||
|
SourceLocation({1, 2}, 4, 6)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SymbolQuery, SourceUsagesAtCallsValues)
|
||||||
|
{
|
||||||
|
EXPECT_CALL(selectSourceUsagesForSymbolLocation, valuesReturnSourceUsages(_, 42, 14, 7));
|
||||||
|
|
||||||
|
query.sourceUsagesAt({1, 42}, 14, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SymbolQuery, SourceUsagesAt)
|
||||||
|
{
|
||||||
|
auto usages = realQuery.sourceUsagesAt({1, 2}, 4, 6);
|
||||||
|
|
||||||
|
ASSERT_THAT(usages,
|
||||||
|
UnorderedElementsAre(CppTools::Usage("/path/to/filename.h", 2, 3),
|
||||||
|
CppTools::Usage("/path/to/filename.cpp", 4, 6)));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,6 @@ SOURCES += \
|
|||||||
mocksqlitereadstatement.cpp \
|
mocksqlitereadstatement.cpp \
|
||||||
symbolquery-test.cpp \
|
symbolquery-test.cpp \
|
||||||
storagesqlitestatementfactory-test.cpp \
|
storagesqlitestatementfactory-test.cpp \
|
||||||
querysqlitestatementfactory-test.cpp \
|
|
||||||
sqliteindex-test.cpp \
|
sqliteindex-test.cpp \
|
||||||
sqlitetransaction-test.cpp \
|
sqlitetransaction-test.cpp \
|
||||||
refactoringdatabaseinitializer-test.cpp \
|
refactoringdatabaseinitializer-test.cpp \
|
||||||
|
|||||||
Reference in New Issue
Block a user