Clang: Check if the include search path has changed

If the include search paths and the compiler macros have not changed it is
save to assume that we don't need to update the symbol database. This saves
us from executing a very expensive task. Later we have to test the
modification time of the files too.

Change-Id: I6b958075024a811c2abd3d7918263fd74bba090b
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
This commit is contained in:
Marco Bubke
2018-02-08 12:48:46 +01:00
parent e7663d0cce
commit 6922f549d5
28 changed files with 204 additions and 65 deletions

View File

@@ -42,11 +42,13 @@ public:
ProjectPartContainer(Utils::SmallString &&projectPartId,
Utils::SmallStringVector &&arguments,
CompilerMacros &&compilerMacros,
Utils::SmallStringVector &&includeSearchPaths,
FilePathIds &&headerPathIds,
FilePathIds &&sourcePathIds)
: m_projectPartId(std::move(projectPartId)),
m_arguments(std::move(arguments)),
m_compilerMacros(std::move(compilerMacros)),
m_includeSearchPaths(std::move(includeSearchPaths)),
m_headerPathIds(std::move(headerPathIds)),
m_sourcePathIds(std::move(sourcePathIds))
{
@@ -72,6 +74,11 @@ public:
return m_compilerMacros;
}
const Utils::SmallStringVector &includeSearchPaths() const
{
return m_includeSearchPaths;
}
const FilePathIds &sourcePathIds() const
{
return m_sourcePathIds;
@@ -87,6 +94,7 @@ public:
out << container.m_projectPartId;
out << container.m_arguments;
out << container.m_compilerMacros;
out << container.m_includeSearchPaths;
out << container.m_headerPathIds;
out << container.m_sourcePathIds;
@@ -98,6 +106,7 @@ public:
in >> container.m_projectPartId;
in >> container.m_arguments;
in >> container.m_compilerMacros;
in >> container.m_includeSearchPaths;
in >> container.m_headerPathIds;
in >> container.m_sourcePathIds;
@@ -109,6 +118,7 @@ public:
return first.m_projectPartId == second.m_projectPartId
&& first.m_arguments == second.m_arguments
&& first.m_compilerMacros == second.m_compilerMacros
&& first.m_includeSearchPaths == second.m_includeSearchPaths
&& first.m_headerPathIds == second.m_headerPathIds
&& first.m_sourcePathIds == second.m_sourcePathIds;
}
@@ -118,11 +128,13 @@ public:
return std::tie(first.m_projectPartId,
first.m_arguments,
first.m_compilerMacros,
first.m_includeSearchPaths,
first.m_headerPathIds,
first.m_sourcePathIds)
< std::tie(second.m_projectPartId,
second.m_arguments,
second.m_compilerMacros,
first.m_includeSearchPaths,
second.m_headerPathIds,
second.m_sourcePathIds);
}
@@ -136,6 +148,7 @@ private:
Utils::SmallString m_projectPartId;
Utils::SmallStringVector m_arguments;
CompilerMacros m_compilerMacros;
Utils::SmallStringVector m_includeSearchPaths;
FilePathIds m_headerPathIds;
FilePathIds m_sourcePathIds;
};

View File

@@ -116,6 +116,7 @@ public:
const Sqlite::Column &projectPartNameColumn = table.addColumn("projectPartName", Sqlite::ColumnType::Text);
table.addColumn("compilerArguments", Sqlite::ColumnType::Text);
table.addColumn("compilerMacros", Sqlite::ColumnType::Text);
table.addColumn("includeSearchPaths", Sqlite::ColumnType::Text);
table.addIndex({projectPartNameColumn});
table.initialize(database);

View File

@@ -121,9 +121,9 @@ QStringList ProjectUpdater::compilerArguments(CppTools::ProjectPart *projectPart
return builder.build(CppTools::ProjectFile::CXXHeader, CompilerOptionsBuilder::PchUsage::None);
}
ClangBackEnd::CompilerMacros ProjectUpdater::createCompilerMacros(CppTools::ProjectPart *projectPart)
ClangBackEnd::CompilerMacros ProjectUpdater::createCompilerMacros(const ProjectExplorer::Macros &projectMacros)
{
auto macros = Utils::transform<ClangBackEnd::CompilerMacros>(projectPart->projectMacros,
auto macros = Utils::transform<ClangBackEnd::CompilerMacros>(projectMacros,
[] (const ProjectExplorer::Macro &macro) {
return ClangBackEnd::CompilerMacro{macro.key, macro.value};
});
@@ -133,6 +133,19 @@ ClangBackEnd::CompilerMacros ProjectUpdater::createCompilerMacros(CppTools::Proj
return macros;
}
Utils::SmallStringVector ProjectUpdater::createIncludeSearchPaths(
const CppTools::ProjectPartHeaderPaths &projectPartHeaderPaths)
{
Utils::SmallStringVector includePaths;
for (const CppTools::ProjectPartHeaderPath &projectPartHeaderPath : projectPartHeaderPaths) {
if (projectPartHeaderPath.isValid())
includePaths.emplace_back(projectPartHeaderPath.path);
}
return includePaths;
}
ClangBackEnd::V2::ProjectPartContainer ProjectUpdater::toProjectPartContainer(
CppTools::ProjectPart *projectPart) const
{
@@ -143,7 +156,8 @@ ClangBackEnd::V2::ProjectPartContainer ProjectUpdater::toProjectPartContainer(
return ClangBackEnd::V2::ProjectPartContainer(projectPart->displayName,
Utils::SmallStringVector(arguments),
createCompilerMacros(projectPart),
createCompilerMacros(projectPart->projectMacros),
createIncludeSearchPaths(projectPart->headerPaths),
std::move(headerAndSources.headers),
std::move(headerAndSources.sources));
}

View File

@@ -31,9 +31,16 @@
#include <filecontainerv2.h>
#include <filepathcachinginterface.h>
namespace ProjectExplorer {
class Macro;
using Macros = QVector<Macro>;
}
namespace CppTools {
class ProjectPart;
class ProjectFile;
class ProjectPartHeaderPath;
using ProjectPartHeaderPaths = QVector<ProjectPartHeaderPath>;
}
namespace ClangBackEnd {
@@ -74,7 +81,10 @@ unittest_public:
void addToHeaderAndSources(HeaderAndSources &headerAndSources,
const CppTools::ProjectFile &projectFile) const;
static QStringList compilerArguments(CppTools::ProjectPart *projectPart);
static ClangBackEnd::CompilerMacros createCompilerMacros(CppTools::ProjectPart *projectPart);
static ClangBackEnd::CompilerMacros createCompilerMacros(
const ProjectExplorer::Macros &projectMacros);
static Utils::SmallStringVector createIncludeSearchPaths(
const CppTools::ProjectPartHeaderPaths &projectPartHeaderPaths);
static Utils::PathStringVector createExcludedPaths(
const ClangBackEnd::V2::FileContainers &generatedFiles);

View File

@@ -33,9 +33,13 @@
namespace ClangBackEnd {
ProjectPartArtefact::ProjectPartArtefact(Utils::SmallStringView compilerArgumentsText, Utils::SmallStringView compilerMacrosText, int projectPartId)
ProjectPartArtefact::ProjectPartArtefact(Utils::SmallStringView compilerArgumentsText,
Utils::SmallStringView compilerMacrosText,
Utils::SmallStringView includeSearchPaths,
int projectPartId)
: compilerArguments(toStringVector(compilerArgumentsText)),
compilerMacros(toCompilerMacros(compilerMacrosText)),
includeSearchPaths(toStringVector(includeSearchPaths)),
projectPartId(projectPartId)
{
}

View File

@@ -41,6 +41,7 @@ class ProjectPartArtefact
public:
ProjectPartArtefact(Utils::SmallStringView compilerArgumentsText,
Utils::SmallStringView compilerMacrosText,
Utils::SmallStringView includeSearchPaths,
int projectPartId);
static
@@ -60,6 +61,7 @@ public:
public:
Utils::SmallStringVector compilerArguments;
CompilerMacros compilerMacros;
Utils::SmallStringVector includeSearchPaths;
int projectPartId = -1;
};

View File

@@ -158,11 +158,11 @@ public:
database
};
WriteStatement insertProjectPartStatement{
"INSERT OR IGNORE INTO projectParts(projectPartName, compilerArguments, compilerMacros) VALUES (?,?,?)",
"INSERT OR IGNORE INTO projectParts(projectPartName, compilerArguments, compilerMacros, includeSearchPaths) VALUES (?,?,?,?)",
database
};
WriteStatement updateProjectPartStatement{
"UPDATE projectParts SET compilerArguments = ?, compilerMacros = ? WHERE projectPartName = ?",
"UPDATE projectParts SET compilerArguments = ?, compilerMacros = ?, includeSearchPaths = ? WHERE projectPartName = ?",
database
};
ReadStatement getProjectPartIdStatement{
@@ -217,12 +217,12 @@ public:
"DELETE FROM newSourceDependencies",
database
};
ReadStatement getProjectPartCompilerArgumentsAndCompilerMacrosBySourceId{
"SELECT compilerArguments, compilerMacros, projectPartId FROM projectParts WHERE projectPartId = (SELECT projectPartId FROM projectPartsSources WHERE sourceId = ?)",
ReadStatement getProjectPartArtefactsBySourceId{
"SELECT compilerArguments, compilerMacros, includeSearchPaths, projectPartId FROM projectParts WHERE projectPartId = (SELECT projectPartId FROM projectPartsSources WHERE sourceId = ?)",
database
};
ReadStatement getProjectPartCompilerArgumentsAndCompilerMacrosByProjectPartName{
"SELECT compilerArguments, compilerMacros, projectPartId FROM projectParts WHERE projectPartName = ?",
ReadStatement getProjectPartArtefactsByProjectPartName{
"SELECT compilerArguments, compilerMacros, includeSearchPaths, projectPartId FROM projectParts WHERE projectPartName = ?",
database
};
};

View File

@@ -52,7 +52,7 @@ void SymbolIndexer::updateProjectPart(V2::ProjectPartContainer &&projectPart,
{
m_symbolsCollector.clear();
if (compilerMacrosAreDifferent(projectPart)) {
if (compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart)) {
m_symbolsCollector.addFiles(projectPart.sourcePathIds(), projectPart.arguments());
m_symbolsCollector.addUnsavedFiles(generatedFiles);
@@ -66,7 +66,8 @@ void SymbolIndexer::updateProjectPart(V2::ProjectPartContainer &&projectPart,
m_symbolStorage.insertOrUpdateProjectPart(projectPart.projectPartId(),
projectPart.arguments(),
projectPart.compilerMacros());
projectPart.compilerMacros(),
projectPart.includeSearchPaths());
m_symbolStorage.updateProjectPartSources(projectPart.projectPartId(),
m_symbolsCollector.sourceFiles());
@@ -121,13 +122,16 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId)
}
}
bool SymbolIndexer::compilerMacrosAreDifferent(const V2::ProjectPartContainer &projectPart) const
bool SymbolIndexer::compilerMacrosOrIncludeSearchPathsAreDifferent(const V2::ProjectPartContainer &projectPart) const
{
const Utils::optional<ProjectPartArtefact> optionalArtefact = m_symbolStorage.fetchProjectPartArtefact(
projectPart.projectPartId());
if (optionalArtefact)
return projectPart.compilerMacros() != optionalArtefact.value().compilerMacros;
if (optionalArtefact) {
const ProjectPartArtefact &artefact = optionalArtefact.value();
return projectPart.compilerMacros() != artefact.compilerMacros
|| projectPart.includeSearchPaths() != artefact.includeSearchPaths;
}
return true;
}

View File

@@ -52,7 +52,8 @@ public:
void pathsChanged(const FilePathIds &filePathIds) override;
void updateChangedPath(FilePathId filePath);
bool compilerMacrosAreDifferent(const V2::ProjectPartContainer &projectPart) const;
bool compilerMacrosOrIncludeSearchPathsAreDifferent(
const V2::ProjectPartContainer &projectPart) const;
private:
SymbolsCollectorInterface &m_symbolsCollector;

View File

@@ -68,34 +68,42 @@ public:
void insertOrUpdateProjectPart(Utils::SmallStringView projectPartName,
const Utils::SmallStringVector &commandLineArguments,
const CompilerMacros &compilerMacros) override
const CompilerMacros &compilerMacros,
const Utils::SmallStringVector &includeSearchPaths) override
{
m_statementFactory.database.setLastInsertedRowId(-1);
Utils::SmallString compilerArguementsAsJson = toJson(commandLineArguments);
Utils::SmallString compilerMacrosAsJson = toJson(compilerMacros);
Utils::SmallString includeSearchPathsAsJason = toJson(includeSearchPaths);
WriteStatement &insertStatement = m_statementFactory.insertProjectPartStatement;
insertStatement.write(projectPartName, compilerArguementsAsJson, compilerMacrosAsJson);
insertStatement.write(projectPartName,
compilerArguementsAsJson,
compilerMacrosAsJson,
includeSearchPathsAsJason);
if (m_statementFactory.database.lastInsertedRowId() == -1) {
WriteStatement &updateStatement = m_statementFactory.updateProjectPartStatement;
updateStatement.write(compilerArguementsAsJson, compilerMacrosAsJson, projectPartName);
updateStatement.write(compilerArguementsAsJson,
compilerMacrosAsJson,
projectPartName,
includeSearchPathsAsJason);
}
}
Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(FilePathId sourceId) const override
{
ReadStatement &statement = m_statementFactory.getProjectPartCompilerArgumentsAndCompilerMacrosBySourceId;
ReadStatement &statement = m_statementFactory.getProjectPartArtefactsBySourceId;
return statement.template value<ProjectPartArtefact, 3>(sourceId.filePathId);
return statement.template value<ProjectPartArtefact, 4>(sourceId.filePathId);
}
Utils::optional<ProjectPartArtefact> fetchProjectPartArtefact(Utils::SmallStringView projectPartName) const override
{
ReadStatement &statement = m_statementFactory.getProjectPartCompilerArgumentsAndCompilerMacrosByProjectPartName;
ReadStatement &statement = m_statementFactory.getProjectPartArtefactsByProjectPartName;
return statement.template value<ProjectPartArtefact, 3>(projectPartName);
return statement.template value<ProjectPartArtefact, 4>(projectPartName);
}
void insertOrUpdateUsedMacros(const UsedMacros &usedMacros) override

View File

@@ -51,7 +51,8 @@ public:
const SourceLocationEntries &sourceLocations) = 0;
virtual void insertOrUpdateProjectPart(Utils::SmallStringView projectPartName,
const Utils::SmallStringVector &commandLineArguments,
const CompilerMacros &compilerMacros) = 0;
const CompilerMacros &compilerMacros,
const Utils::SmallStringVector &includeSearchPaths) = 0;
virtual void updateProjectPartSources(Utils::SmallStringView projectPartName,
const FilePathIds &sourceFilePathIds) = 0;
virtual void updateProjectPartSources(int projectPartId,

View File

@@ -88,14 +88,14 @@ MockSqliteReadStatement::value<Utils::PathString>(const int &directoryId)
template <>
Utils::optional<ClangBackEnd::ProjectPartArtefact>
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartArtefact, 3>(const int& sourceId)
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartArtefact, 4>(const int& sourceId)
{
return valueReturnProjectPartArtefact(sourceId);
}
template <>
Utils::optional<ClangBackEnd::ProjectPartArtefact>
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartArtefact, 3>(const Utils::SmallStringView &projectPartName)
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartArtefact, 4>(const Utils::SmallStringView &projectPartName)
{
return valueReturnProjectPartArtefact(projectPartName);
}

View File

@@ -151,11 +151,11 @@ MockSqliteReadStatement::value<Utils::PathString>(const int&);
template <>
Utils::optional<ClangBackEnd::ProjectPartArtefact>
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartArtefact, 3>(const int&);
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartArtefact, 4>(const int&);
template <>
Utils::optional<ClangBackEnd::ProjectPartArtefact>
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartArtefact, 3>(const Utils::SmallStringView&);
MockSqliteReadStatement::value<ClangBackEnd::ProjectPartArtefact, 4>(const Utils::SmallStringView&);
template <>
Utils::optional<Utils::SmallString>

View File

@@ -61,6 +61,12 @@ public:
MOCK_METHOD3(write,
void (Utils::SmallStringView, Utils::SmallStringView, Utils::SmallStringView));
MOCK_METHOD4(write,
void (Utils::SmallStringView,
Utils::SmallStringView,
Utils::SmallStringView,
Utils::SmallStringView));
MOCK_METHOD1(write,
void (Utils::SmallStringView));

View File

@@ -37,10 +37,11 @@ public:
MOCK_METHOD2(addSymbolsAndSourceLocations,
void(const ClangBackEnd::SymbolEntries &symbolEentries,
const ClangBackEnd::SourceLocationEntries &sourceLocations));
MOCK_METHOD3(insertOrUpdateProjectPart,
MOCK_METHOD4(insertOrUpdateProjectPart,
void(Utils::SmallStringView projectPartName,
const Utils::SmallStringVector &commandLineArgument,
const ClangBackEnd::CompilerMacros &compilerMacros));
const ClangBackEnd::CompilerMacros &compilerMacros,
const Utils::SmallStringVector &includeSearchPaths));
MOCK_METHOD2(updateProjectPartSources,
void(Utils::SmallStringView projectPartName,
const ClangBackEnd::FilePathIds &sourceFilePathIds));

View File

@@ -75,11 +75,13 @@ protected:
ProjectPartContainer projectPart1{"project1",
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1"}},
{"/includes"},
{id(header1Path)},
{id(main1Path)}};
ProjectPartContainer projectPart2{"project2",
{"-I", TESTDATA_DIR, "-x", "c++-header", "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1"}},
{"/includes"},
{id(header2Path)},
{id(main2Path)}};
TestEnvironment environment;

View File

@@ -95,6 +95,7 @@ TEST_F(PchManagerClientServerInProcess, SendUpdatePchProjectPartsMessage)
ProjectPartContainer projectPart2{"projectPartId",
{"-x", "c++-header", "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1"}},
{"/includes"},
{{1, 1}},
{{1, 2}}};
FileContainer fileContainer{{"/path/to/", "file"}, "content", {}};

View File

@@ -71,11 +71,13 @@ protected:
ProjectPartContainer projectPart1{projectPartId1.clone(),
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1"}},
{"/includes"},
{id(header1Path)},
{id(main1Path)}};
ProjectPartContainer projectPart2{projectPartId2.clone(),
{"-x", "c++-header", "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1"}},
{"/includes"},
{id(header2Path)},
{id(main2Path)}};
std::vector<ProjectPartContainer> projectParts{projectPart1, projectPart2};

View File

@@ -33,27 +33,27 @@ using ClangBackEnd::CompilerMacro;
TEST(ProjectPartArtefact, CompilerArguments)
{
ClangBackEnd::ProjectPartArtefact artefact{"[\"-DFoo\",\"-DBar\"]", "", 1};
ClangBackEnd::ProjectPartArtefact artefact{"[\"-DFoo\",\"-DBar\"]", "", "", 1};
ASSERT_THAT(artefact.compilerArguments, ElementsAre(Eq("-DFoo"), Eq("-DBar")));
}
TEST(ProjectPartArtefact, EmptyCompilerArguments)
{
ClangBackEnd::ProjectPartArtefact artefact{"", "", 1};
ClangBackEnd::ProjectPartArtefact artefact{"", "", "", 1};
ASSERT_THAT(artefact.compilerArguments, IsEmpty());
}
TEST(ProjectPartArtefact, CompilerArgumentsParseError)
{
ASSERT_THROW(ClangBackEnd::ProjectPartArtefact("\"-DFoo\",\"-DBar\"]", "", 1),
ASSERT_THROW(ClangBackEnd::ProjectPartArtefact("\"-DFoo\",\"-DBar\"]", "", "", 1),
ClangBackEnd::ProjectPartArtefactParseError);
}
TEST(ProjectPartArtefact, CompilerMacros)
{
ClangBackEnd::ProjectPartArtefact artefact{"", "{\"Foo\":\"1\",\"Bar\":\"42\"}", 1};
ClangBackEnd::ProjectPartArtefact artefact{"", "{\"Foo\":\"1\",\"Bar\":\"42\"}", "", 1};
ASSERT_THAT(artefact.compilerMacros,
UnorderedElementsAre(Eq(CompilerMacro{"Foo", "1"}), Eq(CompilerMacro{"Bar", "42"})));
@@ -61,14 +61,34 @@ TEST(ProjectPartArtefact, CompilerMacros)
TEST(ProjectPartArtefact, EmptyCompilerMacros)
{
ClangBackEnd::ProjectPartArtefact artefact{"", "", 1};
ClangBackEnd::ProjectPartArtefact artefact{"", "", "", 1};
ASSERT_THAT(artefact.compilerMacros, IsEmpty());
}
TEST(ProjectPartArtefact, CompilerMacrosParseError)
{
ASSERT_THROW(ClangBackEnd::ProjectPartArtefact("", "\"Foo\":\"1\",\"Bar\":\"42\"}", 1),
ASSERT_THROW(ClangBackEnd::ProjectPartArtefact("", "\"Foo\":\"1\",\"Bar\":\"42\"}", "", 1),
ClangBackEnd::ProjectPartArtefactParseError);
}
TEST(ProjectPartArtefact, IncludeSearchPaths)
{
ClangBackEnd::ProjectPartArtefact artefact{"", "", "[\"/includes\",\"/other/includes\"]", 1};
ASSERT_THAT(artefact.includeSearchPaths, ElementsAre(Eq("/includes"), Eq("/other/includes")));
}
TEST(ProjectPartArtefact, EmptyIncludeSearchPaths)
{
ClangBackEnd::ProjectPartArtefact artefact{"", "", "", 1};
ASSERT_THAT(artefact.includeSearchPaths, IsEmpty());
}
TEST(ProjectPartArtefact, IncludeSearchPathsParseError)
{
ASSERT_THROW(ClangBackEnd::ProjectPartArtefact("", "", "\"/includes\",\"/other/includes\"]", 1),
ClangBackEnd::ProjectPartArtefactParseError);
}

View File

@@ -50,16 +50,19 @@ protected:
ProjectPartContainer projectPartContainer1{"id",
{"-DUNIX", "-O2"},
{{"DEFINE", "1"}},
{"/includes"},
{firstHeader, secondHeader},
{firstSource, secondSource}};
ProjectPartContainer updatedProjectPartContainer1{"id",
{"-DUNIX", "-O2"},
{{"DEFINE", "1"}},
{"/includes"},
{firstHeader, secondHeader},
{firstSource, secondSource, thirdSource}};
ProjectPartContainer projectPartContainer2{"id2",
{"-DUNIX", "-O2"},
{{"DEFINE", "1"}},
{"/includes"},
{firstHeader, secondHeader},
{firstSource, secondSource}};
};

View File

@@ -51,9 +51,11 @@ using testing::SizeIs;
using testing::NiceMock;
using testing::AnyNumber;
using ClangBackEnd::CompilerMacro;
using ClangBackEnd::V2::FileContainer;
using ClangBackEnd::V2::ProjectPartContainer;
using CppTools::CompilerOptionsBuilder;
using CppTools::ProjectPartHeaderPath;
class ProjectUpdater : public testing::Test
{
@@ -79,12 +81,14 @@ protected:
projectPart.displayName = QString(projectPartId);
projectPart.projectMacros.push_back({"DEFINE", "1"});
Utils::SmallStringVector arguments{ClangPchManager::ProjectUpdater::compilerArguments(
&projectPart)};
expectedContainer = {projectPartId.clone(),
arguments.clone(),
Utils::clone(compilerMacros),
{},
{filePathId(headerPaths[1])},
{filePathIds(sourcePaths)}};
}
@@ -166,6 +170,23 @@ TEST_F(ProjectUpdater, CreateExcludedPaths)
ASSERT_THAT(excludedPaths, ElementsAre("/path/to/header1.h"));
}
TEST_F(ProjectUpdater, CreateCompilerMacros)
{
auto paths = updater.createCompilerMacros({{"DEFINE", "1"}});
ASSERT_THAT(paths, ElementsAre(CompilerMacro{"DEFINE", "1"}));
}
TEST_F(ProjectUpdater, CreateIncludeSearchPaths)
{
ProjectPartHeaderPath includePath{"/to/path", ProjectPartHeaderPath::IncludePath};
ProjectPartHeaderPath invalidPath;
ProjectPartHeaderPath frameworkPath{"/framework/path", ProjectPartHeaderPath::FrameworkPath};
auto paths = updater.createIncludeSearchPaths({includePath, invalidPath, frameworkPath});
ASSERT_THAT(paths, ElementsAre(includePath.path, frameworkPath.path));
}
}

View File

@@ -179,6 +179,7 @@ TEST_F(RefactoringClientServerInProcess, SendUpdatePchProjectPartsMessage)
ProjectPartContainer projectPart2{"projectPartId",
{"-x", "c++-header", "-Wno-pragma-once-outside-header"},
{{"DEFINE", "1"}},
{"/includes"},
{{1, 1}},
{{1, 2}}};
FileContainer fileContainer{{"/path/to/", "file"}, "content", {}};

View File

@@ -86,7 +86,7 @@ TEST_F(RefactoringDatabaseInitializer, AddProjectPartsTable)
{
InSequence s;
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS projectParts(projectPartId INTEGER PRIMARY KEY, projectPartName TEXT, compilerArguments TEXT, compilerMacros TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS projectParts(projectPartId INTEGER PRIMARY KEY, projectPartName TEXT, compilerArguments TEXT, compilerMacros TEXT, includeSearchPaths TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_projectParts_projectPartName ON projectParts(projectPartName)")));
initializer.createProjectPartsTable();
@@ -146,7 +146,7 @@ TEST_F(RefactoringDatabaseInitializer, CreateInTheContructor)
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_sources_directoryId_sourceName ON sources(directoryId, sourceName)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS directories(directoryId INTEGER PRIMARY KEY, directoryPath TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_directories_directoryPath ON directories(directoryPath)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS projectParts(projectPartId INTEGER PRIMARY KEY, projectPartName TEXT, compilerArguments TEXT, compilerMacros TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS projectParts(projectPartId INTEGER PRIMARY KEY, projectPartName TEXT, compilerArguments TEXT, compilerMacros TEXT, includeSearchPaths TEXT)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE INDEX IF NOT EXISTS index_projectParts_projectPartName ON projectParts(projectPartName)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE TABLE IF NOT EXISTS projectPartsSources(projectPartId INTEGER, sourceId INTEGER)")));
EXPECT_CALL(mockDatabase, execute(Eq("CREATE UNIQUE INDEX IF NOT EXISTS index_projectPartsSources_sourceId_projectPartId ON projectPartsSources(sourceId, projectPartId)")));

View File

@@ -302,6 +302,7 @@ TEST_F(RefactoringServer, UpdatePchProjectPartsCallsSymbolIndexingUpdateProjectP
ProjectPartContainers projectParts{{{"projectPartId",
{"-I", TESTDATA_DIR},
{{"DEFINE", "1"}},
{"/includes"},
{filePathId("header1.h")},
{filePathId("main.cpp")}}}};
FileContainers unsaved{{{TESTDATA_DIR, "query_simplefunction.h"},

View File

@@ -169,13 +169,13 @@ TEST_F(StorageSqliteStatementFactory, DeleteNewLocationsTableStatement)
TEST_F(StorageSqliteStatementFactory, InsertProjectPart)
{
ASSERT_THAT(factory.insertProjectPartStatement.sqlStatement,
Eq("INSERT OR IGNORE INTO projectParts(projectPartName, compilerArguments, compilerMacros) VALUES (?,?,?)"));
Eq("INSERT OR IGNORE INTO projectParts(projectPartName, compilerArguments, compilerMacros, includeSearchPaths) VALUES (?,?,?,?)"));
}
TEST_F(StorageSqliteStatementFactory, UpdateProjectPart)
{
ASSERT_THAT(factory.updateProjectPartStatement.sqlStatement,
Eq("UPDATE projectParts SET compilerArguments = ?, compilerMacros = ? WHERE projectPartName = ?"));
Eq("UPDATE projectParts SET compilerArguments = ?, compilerMacros = ?, includeSearchPaths = ? WHERE projectPartName = ?"));
}
TEST_F(StorageSqliteStatementFactory, GetProjectPartIdForProjectPartName)
@@ -258,14 +258,14 @@ TEST_F(StorageSqliteStatementFactory, DeleteAllInNewSourceDependencies)
TEST_F(StorageSqliteStatementFactory, GetProjectPartCompilerArgumentsAndCompilerMacrosBySourceId)
{
ASSERT_THAT(factory.getProjectPartCompilerArgumentsAndCompilerMacrosBySourceId.sqlStatement,
Eq("SELECT compilerArguments, compilerMacros, projectPartId FROM projectParts WHERE projectPartId = (SELECT projectPartId FROM projectPartsSources WHERE sourceId = ?)"));
ASSERT_THAT(factory.getProjectPartArtefactsBySourceId.sqlStatement,
Eq("SELECT compilerArguments, compilerMacros, includeSearchPaths, projectPartId FROM projectParts WHERE projectPartId = (SELECT projectPartId FROM projectPartsSources WHERE sourceId = ?)"));
}
TEST_F(StorageSqliteStatementFactory, GetProjectPartCompilerArgumentsAndCompilerMacrosByProjectPartName)
TEST_F(StorageSqliteStatementFactory, GetProjectPartArtefactsByProjectPartName)
{
ASSERT_THAT(factory.getProjectPartCompilerArgumentsAndCompilerMacrosByProjectPartName.sqlStatement,
Eq("SELECT compilerArguments, compilerMacros, projectPartId FROM projectParts WHERE projectPartName = ?"));
ASSERT_THAT(factory.getProjectPartArtefactsByProjectPartName.sqlStatement,
Eq("SELECT compilerArguments, compilerMacros, includeSearchPaths, projectPartId FROM projectParts WHERE projectPartName = ?"));
}
}

View File

@@ -84,11 +84,13 @@ protected:
ProjectPartContainer projectPart1{"project1",
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
{{"BAR", "1"}, {"FOO", "1"}},
{"/includes"},
{header1PathId},
{main1PathId}};
ProjectPartContainer projectPart2{"project2",
{"-I", TESTDATA_DIR, "-x", "c++-header", "-Wno-pragma-once-outside-header"},
{{"BAR", "1"}, {"FOO", "0"}},
{"/includes"},
{header2PathId},
{main2PathId}};
FileContainers unsaved{{{TESTDATA_DIR, "query_simplefunction.h"},
@@ -100,7 +102,7 @@ protected:
UsedMacros usedMacros{{"Foo", {1, 1}}};
FileStatuses fileStatus{{{1, 2}, 3, 4}};
SourceDependencies sourceDependencies{{{1, 1}, {1, 2}}, {{1, 1}, {1, 3}}};
ClangBackEnd::ProjectPartArtefact artefact{"[\"-DFOO\"]", "{\"FOO\":\"1\",\"BAR\":\"1\"}", 74};
ClangBackEnd::ProjectPartArtefact artefact{"[\"-DFOO\"]", "{\"FOO\":\"1\",\"BAR\":\"1\"}", "[\"/includes\"]", 74};
NiceMock<MockSqliteTransactionBackend> mockSqliteTransactionBackend;
NiceMock<MockSymbolsCollector> mockCollector;
NiceMock<MockSymbolStorage> mockStorage;
@@ -179,10 +181,12 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsUpdateProjectPartsInStorage)
{
EXPECT_CALL(mockStorage, insertOrUpdateProjectPart(Eq("project1"),
ElementsAre("-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"),
ElementsAre(CompilerMacro{"BAR", "1"}, CompilerMacro{"FOO", "1"})));
ElementsAre(CompilerMacro{"BAR", "1"}, CompilerMacro{"FOO", "1"}),
ElementsAre("/includes")));
EXPECT_CALL(mockStorage, insertOrUpdateProjectPart(Eq("project2"),
ElementsAre("-I", TESTDATA_DIR, "-x", "c++-header", "-Wno-pragma-once-outside-header"),
ElementsAre(CompilerMacro{"BAR", "1"}, CompilerMacro{"FOO", "0"})));
ElementsAre(CompilerMacro{"BAR", "1"}, CompilerMacro{"FOO", "0"}),
ElementsAre("/includes")));
indexer.updateProjectParts({projectPart1, projectPart2}, Utils::clone(unsaved));
}
@@ -238,7 +242,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrder)
EXPECT_CALL(mockCollector, collectSymbols());
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin());
EXPECT_CALL(mockStorage, addSymbolsAndSourceLocations(symbolEntries, sourceLocations));
EXPECT_CALL(mockStorage, insertOrUpdateProjectPart(Eq(projectPart1.projectPartId()), Eq(projectPart1.arguments()), Eq(projectPart1.compilerMacros())));
EXPECT_CALL(mockStorage, insertOrUpdateProjectPart(Eq(projectPart1.projectPartId()), Eq(projectPart1.arguments()), Eq(projectPart1.compilerMacros()), Eq(projectPart1.includeSearchPaths())));
EXPECT_CALL(mockStorage, updateProjectPartSources(TypedEq<Utils::SmallStringView>(projectPart1.projectPartId()), Eq(sourceFileIds)));
EXPECT_CALL(mockStorage, insertOrUpdateUsedMacros(Eq(usedMacros)));
EXPECT_CALL(mockStorage, insertFileStatuses(Eq(fileStatus)));
@@ -302,11 +306,11 @@ TEST_F(SymbolIndexer, HandleEmptyOptionalInUpdateChangedPath)
indexer.updateChangedPath(sourceFileIds[0]);
}
TEST_F(SymbolIndexer, CompilerMacrosAreNotDifferent)
TEST_F(SymbolIndexer, CompilerMacrosAndIncludeSearchPathsAreNotDifferent)
{
ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact));
auto areDifferent = indexer.compilerMacrosAreDifferent(projectPart1);
auto areDifferent = indexer.compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart1);
ASSERT_FALSE(areDifferent);
}
@@ -315,7 +319,22 @@ TEST_F(SymbolIndexer, CompilerMacrosAreDifferent)
{
ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact));
auto areDifferent = indexer.compilerMacrosAreDifferent(projectPart2);
auto areDifferent = indexer.compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart2);
ASSERT_TRUE(areDifferent);
}
TEST_F(SymbolIndexer, IncludeSearchPathsAreDifferent)
{
ProjectPartContainer projectPart3{"project3",
{"-I", TESTDATA_DIR, "-Wno-pragma-once-outside-header"},
{{"BAR", "1"}, {"FOO", "1"}},
{"/includes", "/other/includes"},
{header1PathId},
{main1PathId}};
ON_CALL(mockStorage, fetchProjectPartArtefact(An<Utils::SmallStringView>())).WillByDefault(Return(artefact));
auto areDifferent = indexer.compilerMacrosOrIncludeSearchPathsAreDifferent(projectPart3);
ASSERT_TRUE(areDifferent);
}

View File

@@ -88,6 +88,7 @@ protected:
ProjectPartContainer projectPart1{"project1",
{"cc", "-I", TESTDATA_DIR, "-std=c++1z"},
{{"DEFINE", "1"}},
{"/includes"},
{},
{filePathId(main1Path)}};
};

View File

@@ -85,13 +85,13 @@ protected:
MockSqliteWriteStatement &syncNewSourceDependenciesStatement = statementFactory.syncNewSourceDependenciesStatement;
MockSqliteWriteStatement &deleteOutdatedSourceDependenciesStatement = statementFactory.deleteOutdatedSourceDependenciesStatement;
MockSqliteWriteStatement &deleteNewSourceDependenciesStatement = statementFactory.deleteNewSourceDependenciesStatement;
MockSqliteReadStatement &getProjectPartCompilerArgumentsAndCompilerMacrosBySourceId = statementFactory.getProjectPartCompilerArgumentsAndCompilerMacrosBySourceId;
MockSqliteReadStatement &getProjectPartCompilerArgumentsAndCompilerMacrosByProjectPartName = statementFactory.getProjectPartCompilerArgumentsAndCompilerMacrosByProjectPartName;
MockSqliteReadStatement &getProjectPartArtefactsBySourceId = statementFactory.getProjectPartArtefactsBySourceId;
MockSqliteReadStatement &getProjectPartArtefactsByProjectPartName = statementFactory.getProjectPartArtefactsByProjectPartName;
SymbolEntries symbolEntries{{1, {"functionUSR", "function"}},
{2, {"function2USR", "function2"}}};
SourceLocationEntries sourceLocations{{1, {1, 3}, {42, 23}, SymbolType::Declaration},
{2, {1, 4}, {7, 11}, SymbolType::Declaration}};
ClangBackEnd::ProjectPartArtefact artefact{"[\"-DFOO\"]", "{\"FOO\":\"1\"}", 74};
ClangBackEnd::ProjectPartArtefact artefact{"[\"-DFOO\"]", "{\"FOO\":\"1\"}", "[\"/includes\"]", 74};
Storage storage{statementFactory, filePathCache};
};
@@ -190,10 +190,11 @@ TEST_F(SymbolStorage, InsertProjectPart)
EXPECT_CALL(insertProjectPartStatement,
write(TypedEq<Utils::SmallStringView>("project"),
TypedEq<Utils::SmallStringView>("[\"foo\"]"),
TypedEq<Utils::SmallStringView>("{\"FOO\":\"1\"}")));
TypedEq<Utils::SmallStringView>("{\"FOO\":\"1\"}"),
TypedEq<Utils::SmallStringView>("[\"/includes\"]")));
EXPECT_CALL(mockDatabase, lastInsertedRowId());
storage.insertOrUpdateProjectPart("project", {"foo"}, {{"FOO", "1"}});
storage.insertOrUpdateProjectPart("project", {"foo"}, {{"FOO", "1"}}, {"/includes"});
}
TEST_F(SymbolStorage, UpdateProjectPart)
@@ -205,14 +206,16 @@ TEST_F(SymbolStorage, UpdateProjectPart)
EXPECT_CALL(insertProjectPartStatement,
write(TypedEq<Utils::SmallStringView>("project"),
TypedEq<Utils::SmallStringView>("[\"foo\"]"),
TypedEq<Utils::SmallStringView>("{\"FOO\":\"1\"}")));
TypedEq<Utils::SmallStringView>("{\"FOO\":\"1\"}"),
TypedEq<Utils::SmallStringView>("[\"/includes\"]")));
EXPECT_CALL(mockDatabase, lastInsertedRowId());
EXPECT_CALL(updateProjectPartStatement,
write(TypedEq<Utils::SmallStringView>("[\"foo\"]"),
TypedEq<Utils::SmallStringView>("{\"FOO\":\"1\"}"),
TypedEq<Utils::SmallStringView>("project")));
TypedEq<Utils::SmallStringView>("project"),
TypedEq<Utils::SmallStringView>("[\"/includes\"]")));
storage.insertOrUpdateProjectPart("project", {"foo"}, {{"FOO", "1"}});
storage.insertOrUpdateProjectPart("project", {"foo"}, {{"FOO", "1"}}, {"/includes"});
}
TEST_F(SymbolStorage, UpdateProjectPartSources)
@@ -263,7 +266,7 @@ TEST_F(SymbolStorage, InsertOrUpdateSourceDependencies)
TEST_F(SymbolStorage, FetchProjectPartArtefactBySourceIdCallsValueInStatement)
{
EXPECT_CALL(getProjectPartCompilerArgumentsAndCompilerMacrosBySourceId, valueReturnProjectPartArtefact(1))
EXPECT_CALL(getProjectPartArtefactsBySourceId, valueReturnProjectPartArtefact(1))
.WillRepeatedly(Return(artefact));
storage.fetchProjectPartArtefact({2, 1});
@@ -271,7 +274,7 @@ TEST_F(SymbolStorage, FetchProjectPartArtefactBySourceIdCallsValueInStatement)
TEST_F(SymbolStorage, FetchProjectPartArtefactBySourceIdReturnArtefact)
{
EXPECT_CALL(getProjectPartCompilerArgumentsAndCompilerMacrosBySourceId, valueReturnProjectPartArtefact(1))
EXPECT_CALL(getProjectPartArtefactsBySourceId, valueReturnProjectPartArtefact(1))
.WillRepeatedly(Return(artefact));
auto result = storage.fetchProjectPartArtefact({2, 1});
@@ -281,7 +284,7 @@ TEST_F(SymbolStorage, FetchProjectPartArtefactBySourceIdReturnArtefact)
TEST_F(SymbolStorage, FetchProjectPartArtefactByProjectNameCallsValueInStatement)
{
EXPECT_CALL(getProjectPartCompilerArgumentsAndCompilerMacrosBySourceId, valueReturnProjectPartArtefact(1))
EXPECT_CALL(getProjectPartArtefactsBySourceId, valueReturnProjectPartArtefact(1))
.WillRepeatedly(Return(artefact));
storage.fetchProjectPartArtefact({2, 1});
@@ -289,7 +292,7 @@ TEST_F(SymbolStorage, FetchProjectPartArtefactByProjectNameCallsValueInStatement
TEST_F(SymbolStorage, FetchProjectPartArtefactByProjectNameReturnArtefact)
{
EXPECT_CALL(getProjectPartCompilerArgumentsAndCompilerMacrosBySourceId, valueReturnProjectPartArtefact(1))
EXPECT_CALL(getProjectPartArtefactsBySourceId, valueReturnProjectPartArtefact(1))
.WillRepeatedly(Return(artefact));
auto result = storage.fetchProjectPartArtefact({2, 1});