From b9d268977e2220bf86ba23d350bd7a040d7286dc Mon Sep 17 00:00:00 2001 From: Marco Bubke Date: Wed, 18 Oct 2017 13:38:58 +0200 Subject: [PATCH] Clang: Add usage functions to symbol query Change-Id: If68a5119c863e616fea40275136d028abcf441f3 Reviewed-by: Jake Petroules Reviewed-by: Tim Jenssen --- .../querysqlitestatementfactory.h | 5 ++ .../clangrefactoring/sourcelocations.h | 8 ++ src/plugins/clangrefactoring/symbolquery.h | 14 ++++ .../plugins/cpptools/usages.h | 50 +++++++------ .../unit/unittest/gtest-creator-printing.cpp | 15 +++- tests/unit/unittest/gtest-creator-printing.h | 7 ++ .../unit/unittest/mocksqlitereadstatement.cpp | 11 +++ tests/unit/unittest/mocksqlitereadstatement.h | 12 +++ tests/unit/unittest/symbolquery-test.cpp | 73 ++++++++++++++++++- tests/unit/unittest/unittest.pro | 1 - 10 files changed, 169 insertions(+), 27 deletions(-) rename tests/unit/unittest/querysqlitestatementfactory-test.cpp => src/plugins/cpptools/usages.h (53%) diff --git a/src/plugins/clangrefactoring/querysqlitestatementfactory.h b/src/plugins/clangrefactoring/querysqlitestatementfactory.h index b2a7f97cb84..231287e84c1 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 ac13fd38abe..fd0dcf7d7fa 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 75c110eb765..dc4c43b1f29 100644 --- a/src/plugins/clangrefactoring/symbolquery.h +++ b/src/plugins/clangrefactoring/symbolquery.h @@ -30,6 +30,8 @@ #include #include +#include + #include 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(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 d93a4cf8b10..a3cea0f9e51 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 -#include +#include -namespace { +#include +#include -using StatementFactory = ClangRefactoring::QuerySqliteStatementFactory; +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; +using UsagesCallback = std::function; -} +} // namespace CppTools diff --git a/tests/unit/unittest/gtest-creator-printing.cpp b/tests/unit/unittest/gtest-creator-printing.cpp index 6a2545067f1..8c63a0fbda8 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 #include @@ -32,11 +34,12 @@ #include #include +#include + #include #include - 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 73afa782572..136079b3cd7 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 22ad51e7598..1848fea3b26 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.cpp +++ b/tests/unit/unittest/mocksqlitereadstatement.cpp @@ -35,6 +35,17 @@ MockSqliteReadStatement::values(std::size_t reserveSize, return valuesReturnSourceLocations(reserveSize, sourceId, line, column); } +template <> +CppTools::Usages +MockSqliteReadStatement::values( + std::size_t reserveSize, + const int &sourceId, + const int &line, + const int &column) +{ + return valuesReturnSourceUsages(reserveSize, sourceId, line, column); +} + template <> std::vector MockSqliteReadStatement::values(std::size_t reserveSize) { diff --git a/tests/unit/unittest/mocksqlitereadstatement.h b/tests/unit/unittest/mocksqlitereadstatement.h index 3b4c82b5193..ccec595455b 100644 --- a/tests/unit/unittest/mocksqlitereadstatement.h +++ b/tests/unit/unittest/mocksqlitereadstatement.h @@ -32,6 +32,8 @@ #include #include +#include + #include #include @@ -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(std::size_t)); @@ -106,6 +111,13 @@ MockSqliteReadStatement::values( const int &line, const int &column); +template <> +CppTools::Usages +MockSqliteReadStatement::values( + std::size_t reserveSize, + const int &sourceId, + const int &line, + const int &column); template <> std::vector MockSqliteReadStatement::values(std::size_t reserveSize); diff --git a/tests/unit/unittest/symbolquery-test.cpp b/tests/unit/unittest/symbolquery-test.cpp index 6b8988eace4..c402bd64e2f 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 #include +#include +#include #include +#include +#include namespace { @@ -42,13 +45,48 @@ using StatementFactory = QuerySqliteStatementFactory; using Query = ClangRefactoring::SymbolQuery; +struct Data +{ + Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory}; + ClangBackEnd::RefactoringDatabaseInitializer initializer{database}; + using StatementFactory = QuerySqliteStatementFactory; + using Query = ClangRefactoring::SymbolQuery; + StatementFactory statementFactory{database}; + Query query{statementFactory}; +}; class SymbolQuery : public testing::Test { protected: + static void SetUpTestCase() + { + data = std::make_unique(); + 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; NiceMock 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 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 bbe866abb0e..a75f3dc2151 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 \