diff --git a/src/plugins/clangrefactoring/querysqlitestatementfactory.h b/src/plugins/clangrefactoring/querysqlitestatementfactory.h index b2a7f97cb84966b7bb93d571585b2dcb12348d88..231287e84c1ed35c0266ff06203fe6a7eb337cc8 100644 --- a/src/plugins/clangrefactoring/querysqlitestatementfactory.h +++ b/src/plugins/clangrefactoring/querysqlitestatementfactory.h @@ -44,6 +44,11 @@ public: " (SELECT symbolId FROM locations WHERE sourceId=? AND line=? AND column=?) " "ORDER BY sourceId, line, column", 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 diff --git a/src/plugins/clangrefactoring/sourcelocations.h b/src/plugins/clangrefactoring/sourcelocations.h index ac13fd38abee8b06cca2e9503a5b0be8be551207..fd0dcf7d7fade6e35b6b68b54f796251385ce17c 100644 --- a/src/plugins/clangrefactoring/sourcelocations.h +++ b/src/plugins/clangrefactoring/sourcelocations.h @@ -43,6 +43,14 @@ public: : 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; int line; int column; diff --git a/src/plugins/clangrefactoring/symbolquery.h b/src/plugins/clangrefactoring/symbolquery.h index 75c110eb7656c6ca06aa51f4e1ad42af95973edf..dc4c43b1f29e632e5476c369c15c6c1c95edc65b 100644 --- a/src/plugins/clangrefactoring/symbolquery.h +++ b/src/plugins/clangrefactoring/symbolquery.h @@ -30,6 +30,8 @@ #include <filepathid.h> #include <sourcelocations.h> +#include <cpptools/usages.h> + #include <algorithm> namespace ClangRefactoring { @@ -56,6 +58,18 @@ public: 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: StatementFactory &m_statementFactory; }; diff --git a/tests/unit/unittest/querysqlitestatementfactory-test.cpp b/src/plugins/cpptools/usages.h similarity index 53% rename from tests/unit/unittest/querysqlitestatementfactory-test.cpp rename to src/plugins/cpptools/usages.h index d93a4cf8b10b4ec4376ac0be4f255c9e9839efb7..a3cea0f9e5118da82e719cfbe10081bae29d79a0 100644 --- a/tests/unit/unittest/querysqlitestatementfactory-test.cpp +++ b/src/plugins/cpptools/usages.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -23,32 +23,40 @@ ** ****************************************************************************/ -#include "googletest.h" +#pragma once -#include "mocksqlitedatabase.h" -#include "mocksqlitereadstatement.h" -#include "mocksqlitewritestatement.h" +#include <utils/smallstringview.h> -#include <querysqlitestatementfactory.h> +#include <QString> -namespace { +#include <vector> +#include <functional> -using StatementFactory = ClangRefactoring::QuerySqliteStatementFactory<MockSqliteDatabase, - MockSqliteReadStatement>; +namespace CppTools { -class QuerySqliteStatementFactory : public testing::Test +class Usage { -protected: - MockSqliteDatabase mockDatabase; - StatementFactory factory{mockDatabase}; +public: + Usage(Utils::SmallStringView path, int line, int column) + : 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) -{ - 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"); -} +using Usages = std::vector<Usage>; +using UsagesCallback = std::function<void(const Usages &usages)>; -} +} // namespace CppTools diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp index 6a2545067f14092572572ca4784b843537178c74..8c63a0fbda8e7027f947dc4f8f7cc44ec8a35245 100644 --- a/tests/unit/unittest/gtest-creator-printing.cpp +++ b/tests/unit/unittest/gtest-creator-printing.cpp @@ -25,6 +25,8 @@ #include "gtest-creator-printing.h" +#include "gtest-qt-printing.h" + #include <gtest/gtest-printers.h> #include <sourcelocations.h> @@ -32,11 +34,12 @@ #include <sourcelocationentry.h> #include <clangpathwatcher.h> +#include <cpptools/usages.h> + #include <projectexplorer/projectmacro.h> #include <coreplugin/find/searchresultitem.h> - namespace Core { namespace Search { @@ -157,3 +160,13 @@ std::ostream &operator<<(std::ostream &out, const SourceLocation &location) return out << "(" << location.filePathId << ", " << location.line << ", " << location.column << ")"; } } // 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 diff --git a/tests/unit/unittest/gtest-creator-printing.h b/tests/unit/unittest/gtest-creator-printing.h index 73afa78257297c8293bb6ed09fcffa998d11d6db..136079b3cd725eaa253001878f89d0294256e2ed 100644 --- a/tests/unit/unittest/gtest-creator-printing.h +++ b/tests/unit/unittest/gtest-creator-printing.h @@ -78,3 +78,10 @@ class SourceLocation; std::ostream &operator<<(std::ostream &out, const SourceLocation &location); } // namespace ClangRefactoring + + +namespace CppTools { +class Usage; + +std::ostream &operator<<(std::ostream &out, const Usage &usage); +} // namespace CppTools diff --git a/tests/unit/unittest/mocksqlitereadstatement.cpp b/tests/unit/unittest/mocksqlitereadstatement.cpp index 22ad51e7598226ddcc5bd8a5585cc341d7080f27..1848fea3b2677066a53305186e973f1b7bbae76a 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.cpp +++ b/tests/unit/unittest/mocksqlitereadstatement.cpp @@ -35,6 +35,17 @@ MockSqliteReadStatement::values<SourceLocation, 4>(std::size_t reserveSize, 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 <> std::vector<Sources::Directory> MockSqliteReadStatement::values<Sources::Directory, 2>(std::size_t reserveSize) { diff --git a/tests/unit/unittest/mocksqlitereadstatement.h b/tests/unit/unittest/mocksqlitereadstatement.h index 3b4c82b5193aae6d2af74ac3206180b1cfe9857e..ccec595455b4b4205a999c962626260b82f91588 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.h +++ b/tests/unit/unittest/mocksqlitereadstatement.h @@ -32,6 +32,8 @@ #include <filepathstoragesources.h> #include <stringcachefwd.h> +#include <cpptools/usages.h> + #include <utils/optional.h> #include <utils/smallstring.h> @@ -55,6 +57,9 @@ public: MOCK_METHOD4(valuesReturnSourceLocations, SourceLocations(std::size_t, int, int, int)); + MOCK_METHOD4(valuesReturnSourceUsages, + CppTools::Usages(std::size_t, int, int, int)); + MOCK_METHOD1(valuesReturnStdVectorDirectory, std::vector<Sources::Directory>(std::size_t)); @@ -106,6 +111,13 @@ MockSqliteReadStatement::values<SourceLocation, 4>( 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); template <> std::vector<Sources::Directory> MockSqliteReadStatement::values<Sources::Directory, 2>(std::size_t reserveSize); diff --git a/tests/unit/unittest/symbolquery-test.cpp b/tests/unit/unittest/symbolquery-test.cpp index 6b8988eace4b5fe58d7ed3310b69b570fc3654e2..c402bd64e2fe3d2e7438de54f28869314ba3104f 100644 --- a/tests/unit/unittest/symbolquery-test.cpp +++ b/tests/unit/unittest/symbolquery-test.cpp @@ -28,10 +28,13 @@ #include "mocksqlitedatabase.h" #include "mocksqlitereadstatement.h" -#include <symbolquery.h> #include <querysqlitestatementfactory.h> +#include <refactoringdatabaseinitializer.h> +#include <symbolquery.h> #include <sqlitedatabase.h> +#include <sqlitereadstatement.h> +#include <sqlitewritestatement.h> namespace { @@ -42,13 +45,48 @@ using StatementFactory = QuerySqliteStatementFactory<MockSqliteDatabase, MockSqliteReadStatement>; 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 { 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; StatementFactory statementFactory{mockDatabase}; MockSqliteReadStatement &selectLocationsForSymbolLocation = statementFactory.selectLocationsForSymbolLocation; + MockSqliteReadStatement &selectSourceUsagesForSymbolLocation = statementFactory.selectSourceUsagesForSymbolLocation; SourceLocations locations{{{1, 1}, 1, 1}, {{1, 1}, 2, 3}, {{1, 2}, 1, 1}, @@ -56,14 +94,41 @@ protected: {{1, 4}, 1, 1}, {{1, 4}, 1, 3}}; 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)) - .WillRepeatedly(Return(locations)); + EXPECT_CALL(selectLocationsForSymbolLocation, valuesReturnSourceLocations(_, 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))); +} + } diff --git a/tests/unit/unittest/unittest.pro b/tests/unit/unittest/unittest.pro index bbe866abb0e4350f69f9f161cb337cc87b0bec12..a75f3dc215127165eba98bf3af287c6253684a6f 100644 --- a/tests/unit/unittest/unittest.pro +++ b/tests/unit/unittest/unittest.pro @@ -73,7 +73,6 @@ SOURCES += \ mocksqlitereadstatement.cpp \ symbolquery-test.cpp \ storagesqlitestatementfactory-test.cpp \ - querysqlitestatementfactory-test.cpp \ sqliteindex-test.cpp \ sqlitetransaction-test.cpp \ refactoringdatabaseinitializer-test.cpp \