logic: indexer command refactoring

* moved SystemHeaderSearchPaths and FramewordSeearchPaths of indexer cxx indexer commands to CompilerFlags section
* added SourceGroupTestSuite to test indexer command generation of all source groups
* removed "compile_commands.json" from gitignore, because a resource file for the tests has this name
This commit is contained in:
mlangkabel
2018-09-18 17:09:28 +02:00
parent 07454f2045
commit 9dc2bcc2f9
577 changed files with 11357 additions and 9443 deletions
@@ -20,8 +20,6 @@ void SharedIndexerCommand::fromLocal(IndexerCommand* indexerCommand)
setIncludeFilters(cmd->getIncludeFilters());
setWorkingDirectory(cmd->getWorkingDirectory());
setCompilerFlags(cmd->getCompilerFlags());
setSystemHeaderSearchPaths(cmd->getSystemHeaderSearchPaths());
setFrameworkSearchhPaths(cmd->getFrameworkSearchPaths());
}
else if (dynamic_cast<IndexerCommandJava*>(indexerCommand) != nullptr)
{
@@ -50,8 +48,6 @@ std::shared_ptr<IndexerCommand> SharedIndexerCommand::fromShared(const SharedInd
indexerCommand.getExcludeFilters(),
indexerCommand.getIncludeFilters(),
indexerCommand.getWorkingDirectory(),
indexerCommand.getSystemHeaderSearchPaths(),
indexerCommand.getFrameworkSearchhPaths(),
indexerCommand.getCompilerFlags()
);
return command;
@@ -83,8 +79,6 @@ SharedIndexerCommand::SharedIndexerCommand(SharedMemory::Allocator* allocator)
, m_workingDirectory("", allocator)
, m_languageStandard("", allocator)
, m_compilerFlags(allocator)
, m_systemHeaderSearchPaths(allocator)
, m_frameworkSearchPaths(allocator)
, m_classPaths(allocator)
{
}
@@ -221,58 +215,6 @@ void SharedIndexerCommand::setCompilerFlags(const std::vector<std::wstring>& com
}
}
std::vector<FilePath> SharedIndexerCommand::getSystemHeaderSearchPaths() const
{
std::vector<FilePath> result;
result.reserve(m_systemHeaderSearchPaths.size());
for (unsigned int i = 0; i < m_systemHeaderSearchPaths.size(); i++)
{
result.push_back(FilePath(utility::decodeFromUtf8(m_systemHeaderSearchPaths[i].c_str())));
}
return result;
}
void SharedIndexerCommand::setSystemHeaderSearchPaths(const std::vector<FilePath>& filePaths)
{
m_systemHeaderSearchPaths.clear();
m_systemHeaderSearchPaths.reserve(filePaths.size());
for (const FilePath& filePath : filePaths)
{
SharedMemory::String path(m_systemHeaderSearchPaths.get_allocator());
path = utility::encodeToUtf8(filePath.wstr()).c_str();
m_systemHeaderSearchPaths.push_back(path);
}
}
std::vector<FilePath> SharedIndexerCommand::getFrameworkSearchhPaths() const
{
std::vector<FilePath> result;
result.reserve(m_frameworkSearchPaths.size());
for (unsigned int i = 0; i < m_frameworkSearchPaths.size(); i++)
{
result.push_back(FilePath(utility::decodeFromUtf8(m_frameworkSearchPaths[i].c_str())));
}
return result;
}
void SharedIndexerCommand::setFrameworkSearchhPaths(const std::vector<FilePath>& searchPaths)
{
m_frameworkSearchPaths.clear();
m_frameworkSearchPaths.reserve(searchPaths.size());
for (const FilePath& searchPath : searchPaths)
{
SharedMemory::String path(m_frameworkSearchPaths.get_allocator());
path = utility::encodeToUtf8(searchPath.wstr()).c_str();
m_frameworkSearchPaths.push_back(path);
}
}
std::vector<FilePath> SharedIndexerCommand::getClassPaths() const
{
std::vector<FilePath> result;
@@ -39,12 +39,6 @@ public:
std::vector<std::wstring> getCompilerFlags() const;
void setCompilerFlags(const std::vector<std::wstring>& compilerFlags);
std::vector<FilePath> getSystemHeaderSearchPaths() const;
void setSystemHeaderSearchPaths(const std::vector<FilePath>& filePaths);
std::vector<FilePath> getFrameworkSearchhPaths() const;
void setFrameworkSearchhPaths(const std::vector<FilePath>& searchPaths);
std::vector<FilePath> getClassPaths() const;
void setClassPaths(const std::vector<FilePath>& classPaths);
@@ -71,8 +65,6 @@ private:
SharedMemory::String m_workingDirectory;
SharedMemory::String m_languageStandard;
SharedMemory::Vector<SharedMemory::String> m_compilerFlags;
SharedMemory::Vector<SharedMemory::String> m_systemHeaderSearchPaths;
SharedMemory::Vector<SharedMemory::String> m_frameworkSearchPaths;
// java
SharedMemory::Vector<SharedMemory::String> m_classPaths;
@@ -200,15 +200,17 @@ namespace Sonargraph
LOG_ERROR(L"Source group doesn't specify any indexed header paths");
}
const std::vector<FilePath> systemHeaderSearchPaths = (appSettings ? appSettings->getHeaderSearchPathsExpanded() : std::vector<FilePath>());
const std::vector<FilePath> frameworkSearchPaths = (appSettings ? appSettings->getFrameworkSearchPathsExpanded() : std::vector<FilePath>());
std::vector<std::wstring> compilerFlags;
compilerFlags.emplace_back(IndexerCommandCxx::getCompilerFlagLanguageStandard(languageStandard));
utility::append(compilerFlags, IndexerCommandCxx::getCompilerFlagsForSystemHeaderSearchPaths(appSettings ? appSettings->getHeaderSearchPathsExpanded() : std::vector<FilePath>()));
utility::append(compilerFlags, IndexerCommandCxx::getCompilerFlagsForFrameworkSearchPaths(appSettings ? appSettings->getFrameworkSearchPathsExpanded() : std::vector<FilePath>()));
for (std::shared_ptr<XsdRootPath> rootPath : getRootPaths())
{
if (std::shared_ptr<XsdRootPathWithFiles> rootPathWithFiles = std::dynamic_pointer_cast<XsdRootPathWithFiles>(rootPath))
{
utility::append(indexerCommands, getIndexerCommandsForRootPath(
rootPathWithFiles, indexedHeaderPaths, languageStandard, systemHeaderSearchPaths, frameworkSearchPaths
rootPathWithFiles, indexedHeaderPaths, compilerFlags
));
}
}
@@ -216,7 +218,7 @@ namespace Sonargraph
for (std::shared_ptr<XsdRootPathWithFiles> rootPath : m_rootPathWithFiles)
{
utility::append(indexerCommands, getIndexerCommandsForRootPath(
rootPath, indexedHeaderPaths, languageStandard, systemHeaderSearchPaths, frameworkSearchPaths
rootPath, indexedHeaderPaths, compilerFlags
));
}
@@ -294,9 +296,7 @@ namespace Sonargraph
std::vector<std::shared_ptr<IndexerCommand>> XsdCmakeJsonModule::getIndexerCommandsForRootPath(
std::shared_ptr<XsdRootPathWithFiles> rootPath,
const std::set<FilePath>& indexedHeaderPaths,
const std::wstring& languageStandard,
const std::vector<FilePath>& systemHeaderSearchPaths,
const std::vector<FilePath>& frameworkSearchPaths) const
const std::vector<std::wstring>& compilerFlags) const
{
std::vector<std::shared_ptr<IndexerCommand>> indexerCommands;
if (rootPath)
@@ -319,11 +319,11 @@ namespace Sonargraph
{
if (systemExtension->hasCompilerOptionsForId(id))
{
return systemExtension->getCompilerOptionsForId(id);
return utility::concat(systemExtension->getCompilerOptionsForId(id), compilerFlags);
}
}
}
return std::vector<std::wstring>();
return compilerFlags;
});
for (const XsdRootPathWithFiles::SourceFile& sourceFile : getIncludedSourceFilesForRootPath(
@@ -337,14 +337,9 @@ namespace Sonargraph
excludeFilters,
includeFilters,
softwareSystem->getBaseDirectory(),
systemHeaderSearchPaths,
frameworkSearchPaths,
utility::concat(
compilerOptionCache.getValue(sourceFile.compilerOptionSetId),
{
L"-std=" + languageStandard,
sourceFilePath.wstr()
}
sourceFilePath.wstr()
)
));
}
@@ -34,9 +34,7 @@ namespace Sonargraph
std::vector<std::shared_ptr<IndexerCommand>> getIndexerCommandsForRootPath(
std::shared_ptr<XsdRootPathWithFiles> rootPath,
const std::set<FilePath>& indexedHeaderPaths,
const std::wstring& languageStandard,
const std::vector<FilePath>& systemHeaderSearchPaths,
const std::vector<FilePath>& frameworkSearchPaths) const;
const std::vector<std::wstring>& compilerFlags) const;
std::vector<std::shared_ptr<XsdRootPathWithFiles>> m_rootPathWithFiles;
};
@@ -150,8 +150,6 @@ namespace Sonargraph
return std::vector<std::shared_ptr<IndexerCommand>>();
}
std::vector<std::shared_ptr<IndexerCommand>> indexerCommands;
std::set<FilePath> indexedHeaderPaths;
std::wstring languageStandard = SourceGroupSettingsWithCppStandard::getDefaultCppStandardStatic();
@@ -167,13 +165,10 @@ namespace Sonargraph
LOG_ERROR(L"Source group doesn't specify any indexed header paths");
}
const std::vector<FilePath> systemHeaderSearchPaths = (appSettings ? appSettings->getHeaderSearchPathsExpanded() : std::vector<FilePath>());
const std::vector<FilePath> frameworkSearchPaths = (appSettings ? appSettings->getFrameworkSearchPathsExpanded() : std::vector<FilePath>());
const std::set<FilePathFilter> excludeFilters = utility::toSet(getDerivedExcludeFilters());
const std::set<FilePathFilter> includeFilters = utility::toSet(getDerivedIncludeFilters());
std::vector<std::wstring> processedOptions;
std::vector<std::wstring> compilerFlags;
{
const std::vector<std::wstring> optionPrefixes = getIncludeOptionPrefixes();
const FilePath baseIncludeDir = m_basePathForIncludes.isAbsolute() ? m_basePathForIncludes : softwareSystem->getBaseDirectory().getConcatenated(m_basePathForIncludes);
@@ -187,16 +182,16 @@ namespace Sonargraph
{
isIncludeOption = true;
processedOptions.push_back(L"-isystem");
compilerFlags.push_back(L"-isystem");
FilePath headerSearchPath(utility::trim(compilerOption.substr(optionPrefix.size())));
if (headerSearchPath.isAbsolute())
{
processedOptions.push_back(headerSearchPath.wstr());
compilerFlags.push_back(headerSearchPath.wstr());
}
else
{
processedOptions.push_back(baseIncludeDir.getConcatenated(headerSearchPath).wstr());
compilerFlags.push_back(baseIncludeDir.getConcatenated(headerSearchPath).wstr());
}
break;
}
@@ -204,13 +199,16 @@ namespace Sonargraph
if (!isIncludeOption)
{
processedOptions.push_back(compilerOption);
compilerFlags.push_back(compilerOption);
}
}
}
processedOptions.push_back(L"-std=" + languageStandard);
compilerFlags.emplace_back(IndexerCommandCxx::getCompilerFlagLanguageStandard(languageStandard));
utility::append(compilerFlags, IndexerCommandCxx::getCompilerFlagsForSystemHeaderSearchPaths(appSettings ? appSettings->getHeaderSearchPathsExpanded() : std::vector<FilePath>()));
utility::append(compilerFlags, IndexerCommandCxx::getCompilerFlagsForFrameworkSearchPaths(appSettings ? appSettings->getFrameworkSearchPathsExpanded() : std::vector<FilePath>()));
std::vector<std::shared_ptr<IndexerCommand>> indexerCommands;
for (const FilePath& sourceFilePath : getAllSourceFilePathsCanonical())
{
indexerCommands.push_back(std::make_shared<IndexerCommandCxx>(
@@ -219,9 +217,7 @@ namespace Sonargraph
excludeFilters,
includeFilters,
softwareSystem->getBaseDirectory(),
systemHeaderSearchPaths,
frameworkSearchPaths,
utility::concat(processedOptions, { sourceFilePath.wstr() })
utility::concat(compilerFlags, sourceFilePath.wstr())
));
}
+23
View File
@@ -37,6 +37,12 @@ namespace utility
template<typename T>
std::set<T> concat(const std::set<T>& a, const std::set<T>& b);
template<typename T>
std::vector<T> concat(const std::vector<T>& a, const T& b);
template<typename T>
std::set<T> concat(const std::set<T>& a, const T& b);
template<typename T>
void append(std::vector<T>& a, const std::vector<T>& b);
@@ -162,6 +168,7 @@ template<typename T>
std::vector<T> utility::concat(const std::vector<T>& a, const std::vector<T>& b)
{
std::vector<T> r;
r.reserve(a.size() + b.size());
append(r, a);
append(r, b);
return r;
@@ -176,6 +183,22 @@ std::set<T> utility::concat(const std::set<T>& a, const std::set<T>& b)
return r;
}
template<typename T>
std::vector<T> utility::concat(const std::vector<T>& a, const T& b)
{
std::vector<T> r = a;
r.emplace_back(b);
return r;
}
template<typename T>
std::set<T> utility::concat(const std::set<T>& a, const T& b)
{
std::set<T> r = a;
r.emplace(b);
return r;
}
template<typename T>
void utility::append(std::vector<T>& a, const std::vector<T>& b)
{
@@ -102,46 +102,6 @@ void CxxIndexerCommandProvider::addCommand(const std::shared_ptr<IndexerCommandC
}
}
{
const std::vector<FilePath>& systemHeaderSearchPaths = command->getSystemHeaderSearchPaths();
representation->m_systemHeaderSearchPathIds.reserve(systemHeaderSearchPaths.size());
for (const FilePath& systemHeaderSearchPath : systemHeaderSearchPaths)
{
std::map<FilePath, Id>::const_iterator it = m_systemHeaderSearchPathsToIds.find(systemHeaderSearchPath);
if (it != m_systemHeaderSearchPathsToIds.end())
{
representation->m_systemHeaderSearchPathIds.emplace_back(it->second);
}
else
{
const Id id = getId();
m_systemHeaderSearchPathsToIds[systemHeaderSearchPath] = id;
m_idsToSystemHeaderSearchPaths[id] = systemHeaderSearchPath;
representation->m_systemHeaderSearchPathIds.emplace_back(id);
}
}
}
{
const std::vector<FilePath>& frameworkSearchPaths = command->getFrameworkSearchPaths();
representation->m_frameworkSearchPathIds.reserve(frameworkSearchPaths.size());
for (const FilePath& frameworkSearchPath : frameworkSearchPaths)
{
std::map<FilePath, Id>::const_iterator it = m_frameworkSearchPathsToIds.find(frameworkSearchPath);
if (it != m_frameworkSearchPathsToIds.end())
{
representation->m_frameworkSearchPathIds.emplace_back(it->second);
}
else
{
const Id id = getId();
m_frameworkSearchPathsToIds[frameworkSearchPath] = id;
m_idsToFrameworkSearchPaths[id] = frameworkSearchPath;
representation->m_frameworkSearchPathIds.emplace_back(id);
}
}
}
m_commands[command->getSourceFilePath()] = representation;
}
@@ -214,8 +174,6 @@ void CxxIndexerCommandProvider::logStats() const
LOG_INFO("\texclude filter count: " + std::to_string(m_idsToExcludeFilters.size()));
LOG_INFO("\tinclude filter count: " + std::to_string(m_idsToIncludeFilters.size()));
LOG_INFO("\tworking directory count: " + std::to_string(m_idsToWorkingDirectories.size()));
LOG_INFO("\theader search paths count: " + std::to_string(m_idsToSystemHeaderSearchPaths.size()));
LOG_INFO("\tframework search path count: " + std::to_string(m_idsToFrameworkSearchPaths.size()));
LOG_INFO("\tcompiler flag count: " + std::to_string(m_idsToCompilerFlags.size()));
}
@@ -252,26 +210,12 @@ std::shared_ptr<IndexerCommandCxx> CxxIndexerCommandProvider::represetationToCom
compilerFlags.push_back(m_idsToCompilerFlags[id]);
}
std::vector<FilePath> systemHeaderSearchPaths;
for (const Id id : representation->m_systemHeaderSearchPathIds)
{
systemHeaderSearchPaths.push_back(m_idsToSystemHeaderSearchPaths[id]);
}
std::vector<FilePath> frameworkSearchPaths;
for (const Id id : representation->m_frameworkSearchPathIds)
{
frameworkSearchPaths.push_back(m_idsToFrameworkSearchPaths[id]);
}
return std::make_shared<IndexerCommandCxx>(
sourceFilePath,
indexedPaths,
excludeFilters,
includeFilters,
workingDirectory,
systemHeaderSearchPaths,
frameworkSearchPaths,
compilerFlags
);
}
@@ -31,8 +31,6 @@ private:
std::set<Id> m_excludeFilterIds;
std::set<Id> m_includeFilterIds;
Id m_workingDirectoryId;
std::vector<Id> m_systemHeaderSearchPathIds;
std::vector<Id> m_frameworkSearchPathIds;
std::vector<Id> m_compilerFlagIds;
};
@@ -51,10 +49,6 @@ private:
std::map<std::wstring, Id> m_includeFiltersToIds;
std::map<Id, FilePath> m_idsToWorkingDirectories;
std::map<FilePath, Id> m_workingDirectoriesToIds;
std::map<Id, FilePath> m_idsToSystemHeaderSearchPaths;
std::map<FilePath, Id> m_systemHeaderSearchPathsToIds;
std::map<Id, FilePath> m_idsToFrameworkSearchPaths;
std::map<FilePath, Id> m_frameworkSearchPathsToIds;
std::map<Id, std::wstring> m_idsToCompilerFlags;
std::unordered_map<std::wstring, Id> m_compilerFlagsToIds;
};
+44 -42
View File
@@ -8,6 +8,8 @@
#include "utility/logging/logging.h"
#include "utility/messaging/type/MessageStatus.h"
#include "utility/OrderedCache.h"
#include "utility/ResourcePaths.h"
#include "utility/utility.h"
#include "utility/utilityString.h"
std::vector<FilePath> IndexerCommandCxx::getSourceFilesFromCDB(const FilePath& compilationDatabasePath)
@@ -36,16 +38,56 @@ std::vector<FilePath> IndexerCommandCxx::getSourceFilesFromCDB(const FilePath& c
std::vector<clang::tooling::CompileCommand> commands = cdb->getCompileCommands(fileString);
if (!commands.empty())
{
path = FilePath(utility::decodeFromUtf8(commands.front().Directory + '/' + commands.front().Filename));
path = FilePath(utility::decodeFromUtf8(commands.front().Directory + '/' + commands.front().Filename)).makeCanonical();
}
}
if (!path.isAbsolute())
{
path = compilationDatabasePath.getParentDirectory().getConcatenated(path).makeCanonical();
}
filePaths.push_back(canonicalDirectoryPathCache.getValue(path.getParentDirectory()).concatenate(path.fileName()));
}
}
return filePaths;
}
std::wstring IndexerCommandCxx::getCompilerFlagLanguageStandard(const std::wstring &languageStandard)
{
return L"-std=" + languageStandard;
}
std::vector<std::wstring> IndexerCommandCxx::getCompilerFlagsForSystemHeaderSearchPaths(const std::vector<FilePath>& systemHeaderSearchPaths)
{
std::vector<std::wstring> compilerFlags;
compilerFlags.reserve(systemHeaderSearchPaths.size() * 2);
for (const FilePath& path : systemHeaderSearchPaths)
{
#ifdef _WIN32
// prepend clang system includes on windows
if (path == ResourcePaths::getCxxCompilerHeaderPath())
{
compilerFlags = utility::concat({ L"-isystem" , path.wstr() }, compilerFlags);
continue;
}
#endif
compilerFlags.push_back(L"-isystem");
compilerFlags.push_back(path.wstr());
}
return compilerFlags;
}
std::vector<std::wstring> IndexerCommandCxx::getCompilerFlagsForFrameworkSearchPaths(const std::vector<FilePath>& frameworkSearchPaths)
{
std::vector<std::wstring> compilerFlags;
compilerFlags.reserve(frameworkSearchPaths.size() * 2);
for (const FilePath& path : frameworkSearchPaths)
{
compilerFlags.push_back(L"-iframework");
compilerFlags.push_back(path.wstr());
}
return compilerFlags;
}
IndexerCommandType IndexerCommandCxx::getStaticIndexerCommandType()
{
return INDEXER_COMMAND_CXX;
@@ -57,8 +99,6 @@ IndexerCommandCxx::IndexerCommandCxx(
const std::set<FilePathFilter>& excludeFilters,
const std::set<FilePathFilter>& includeFilters,
const FilePath& workingDirectory,
const std::vector<FilePath>& systemHeaderSearchPaths,
const std::vector<FilePath>& frameworkSearchPaths,
const std::vector<std::wstring>& compilerFlags
)
: IndexerCommand(sourceFilePath)
@@ -66,8 +106,6 @@ IndexerCommandCxx::IndexerCommandCxx(
, m_excludeFilters(excludeFilters)
, m_includeFilters(includeFilters)
, m_workingDirectory(workingDirectory)
, m_systemHeaderSearchPaths(systemHeaderSearchPaths)
, m_frameworkSearchPaths(frameworkSearchPaths)
, m_compilerFlags(compilerFlags)
{
}
@@ -96,16 +134,6 @@ size_t IndexerCommandCxx::getByteSize(size_t stringSize) const
size += stringSize + utility::encodeToUtf8(filter.wstr()).size();
}
for (const FilePath& path : m_systemHeaderSearchPaths)
{
size += stringSize + utility::encodeToUtf8(path.wstr()).size();
}
for (const FilePath& path : m_frameworkSearchPaths)
{
size += stringSize + utility::encodeToUtf8(path.wstr()).size();
}
for (const std::wstring& flag : m_compilerFlags)
{
size += stringSize + flag.size();
@@ -129,16 +157,6 @@ const std::set<FilePathFilter>& IndexerCommandCxx::getIncludeFilters() const
return m_includeFilters;
}
const std::vector<FilePath>& IndexerCommandCxx::getSystemHeaderSearchPaths() const
{
return m_systemHeaderSearchPaths;
}
const std::vector<FilePath>& IndexerCommandCxx::getFrameworkSearchPaths() const
{
return m_frameworkSearchPaths;
}
const std::vector<std::wstring>& IndexerCommandCxx::getCompilerFlags() const
{
return m_compilerFlags;
@@ -180,22 +198,6 @@ QJsonObject IndexerCommandCxx::doSerialize() const
{
jsonObject["working_directory"] = QString::fromStdWString(getWorkingDirectory().wstr());
}
{
QJsonArray systemHeaderSearchPathsArray;
for (const FilePath& systemHeaderSearchPath : m_systemHeaderSearchPaths)
{
systemHeaderSearchPathsArray.append(QString::fromStdWString(systemHeaderSearchPath.wstr()));
}
jsonObject["system_header_search_paths"] = systemHeaderSearchPathsArray;
}
{
QJsonArray frameworkSearchPathsArray;
for (const FilePath& frameworkSearchPath : m_frameworkSearchPaths)
{
frameworkSearchPathsArray.append(QString::fromStdWString(frameworkSearchPath.wstr()));
}
jsonObject["framework_search_paths"] = frameworkSearchPathsArray;
}
{
QJsonArray compilerFlagsArray;
for (const std::wstring& compilerFlag : m_compilerFlags)
+3 -6
View File
@@ -13,6 +13,9 @@ class IndexerCommandCxx
{
public:
static std::vector<FilePath> getSourceFilesFromCDB(const FilePath& compilationDatabasePath);
static std::wstring getCompilerFlagLanguageStandard(const std::wstring &languageStandard);
static std::vector<std::wstring> getCompilerFlagsForSystemHeaderSearchPaths(const std::vector<FilePath>& systemHeaderSearchPaths);
static std::vector<std::wstring> getCompilerFlagsForFrameworkSearchPaths(const std::vector<FilePath>& frameworkSearchPaths);
static IndexerCommandType getStaticIndexerCommandType();
@@ -22,8 +25,6 @@ public:
const std::set<FilePathFilter>& excludeFilters,
const std::set<FilePathFilter>& includeFilters,
const FilePath& workingDirectory,
const std::vector<FilePath>& systemHeaderSearchPaths,
const std::vector<FilePath>& frameworkSearchPaths,
const std::vector<std::wstring>& compilerFlags);
IndexerCommandType getIndexerCommandType() const override;
@@ -32,8 +33,6 @@ public:
const std::set<FilePath>& getIndexedPaths() const;
const std::set<FilePathFilter>& getExcludeFilters() const;
const std::set<FilePathFilter>& getIncludeFilters() const;
const std::vector<FilePath>& getSystemHeaderSearchPaths() const;
const std::vector<FilePath>& getFrameworkSearchPaths() const;
const std::vector<std::wstring>& getCompilerFlags() const;
const FilePath& getWorkingDirectory() const;
@@ -45,8 +44,6 @@ private:
std::set<FilePathFilter> m_excludeFilters;
std::set<FilePathFilter> m_includeFilters;
FilePath m_workingDirectory;
std::vector<FilePath> m_systemHeaderSearchPaths;
std::vector<FilePath> m_frameworkSearchPaths;
std::vector<std::wstring> m_compilerFlags;
};
+5 -29
View File
@@ -93,7 +93,7 @@ namespace
std::vector<std::string> prependSyntaxOnlyToolArgs(const std::vector<std::string>& args)
{
return utility::concat({ "clang-tool", "-fsyntax-only" }, args);
return utility::concat(std::vector<std::string>({ "clang-tool", "-fsyntax-only" }), args);
}
std::vector<std::string> appendFilePath(const std::vector<std::string>& args, llvm::StringRef filePath)
@@ -143,9 +143,7 @@ void CxxParser::buildIndex(std::shared_ptr<IndexerCommandCxx> indexerCommand)
clang::tooling::CompileCommand compileCommand;
compileCommand.Filename = utility::encodeToUtf8(indexerCommand->getSourceFilePath().wstr());
compileCommand.Directory = utility::encodeToUtf8(indexerCommand->getWorkingDirectory().wstr());
compileCommand.CommandLine = getCommandlineArgumentsEssential(
indexerCommand->getCompilerFlags(), indexerCommand->getSystemHeaderSearchPaths(), indexerCommand->getFrameworkSearchPaths()
);
compileCommand.CommandLine = getCommandlineArgumentsEssential(indexerCommand->getCompilerFlags());
if (!utility::isPrefix<std::string>("-", compileCommand.CommandLine.front()))
{
@@ -165,7 +163,7 @@ void CxxParser::buildIndex(const std::wstring& fileName, std::shared_ptr<TextAcc
std::shared_ptr<CxxDiagnosticConsumer> diagnostics = getDiagnostics(FilePath(), canonicalFilePathCache, false);
ASTActionFactory actionFactory(m_client, canonicalFilePathCache);
std::vector<std::string> args = getCommandlineArgumentsEssential(compilerFlags, std::vector<FilePath>(), std::vector<FilePath>());
std::vector<std::string> args = getCommandlineArgumentsEssential(compilerFlags);
runToolOnCodeWithArgs(
diagnostics.get(),
@@ -197,11 +195,8 @@ void CxxParser::runTool(clang::tooling::CompilationDatabase* compilationDatabase
tool.run(&actionFactory);
}
std::vector<std::string> CxxParser::getCommandlineArgumentsEssential(
const std::vector<std::wstring>& compilerFlags,
const std::vector<FilePath>& systemHeaderSearchPaths,
const std::vector<FilePath>& frameworkSearchPaths
) const {
std::vector<std::string> CxxParser::getCommandlineArgumentsEssential(const std::vector<std::wstring>& compilerFlags) const
{
std::vector<std::string> args;
// The option -fno-delayed-template-parsing signals that templates that there should
@@ -225,25 +220,6 @@ std::vector<std::string> CxxParser::getCommandlineArgumentsEssential(
args.push_back(utility::encodeToUtf8(compilerFlag));
}
for (const FilePath& path : systemHeaderSearchPaths)
{
#ifdef _WIN32
if (path == ResourcePaths::getCxxCompilerHeaderPath())
{
args = utility::concat({ "-isystem" , utility::encodeToUtf8(path.wstr()) }, args);
continue;
}
#endif
args.push_back("-isystem");
args.push_back(utility::encodeToUtf8(path.wstr()));
}
for (const FilePath& path: frameworkSearchPaths)
{
args.push_back("-iframework");
args.push_back(utility::encodeToUtf8(path.wstr()));
}
return args;
}
+1 -4
View File
@@ -32,10 +32,7 @@ public:
private:
void runTool(clang::tooling::CompilationDatabase* compilationDatabase, const FilePath& sourceFilePath);
std::vector<std::string> getCommandlineArgumentsEssential(
const std::vector<std::wstring>& compilerFlags,
const std::vector<FilePath>& systemHeaderSearchPaths,
const std::vector<FilePath>& frameworkSearchPaths) const;
std::vector<std::string> getCommandlineArgumentsEssential(const std::vector<std::wstring>& compilerFlags) const;
std::shared_ptr<CxxDiagnosticConsumer> getDiagnostics(
const FilePath& sourceFilePath, std::shared_ptr<CanonicalFilePathCache> canonicalFilePathCache, bool logErrors) const;
+12 -9
View File
@@ -88,15 +88,16 @@ std::shared_ptr<IndexerCommandProvider> SourceGroupCxxCdb::getIndexerCommandProv
{
std::shared_ptr<ApplicationSettings> appSettings = ApplicationSettings::getInstance();
std::vector<FilePath> systemHeaderSearchPaths;
utility::append(systemHeaderSearchPaths, m_settings->getHeaderSearchPathsExpandedAndAbsolute());
utility::append(systemHeaderSearchPaths, appSettings->getHeaderSearchPathsExpanded());
std::vector<std::wstring> compilerFlags;
{
utility::append(compilerFlags, IndexerCommandCxx::getCompilerFlagsForSystemHeaderSearchPaths(m_settings->getHeaderSearchPathsExpandedAndAbsolute()));
utility::append(compilerFlags, IndexerCommandCxx::getCompilerFlagsForSystemHeaderSearchPaths(appSettings->getHeaderSearchPathsExpanded()));
std::vector<FilePath> frameworkSearchPaths;
utility::append(frameworkSearchPaths, m_settings->getFrameworkSearchPathsExpandedAndAbsolute());
utility::append(frameworkSearchPaths, appSettings->getFrameworkSearchPathsExpanded());
utility::append(compilerFlags, IndexerCommandCxx::getCompilerFlagsForFrameworkSearchPaths(m_settings->getFrameworkSearchPathsExpandedAndAbsolute()));
utility::append(compilerFlags, IndexerCommandCxx::getCompilerFlagsForFrameworkSearchPaths(appSettings->getFrameworkSearchPathsExpanded()));
const std::vector<std::wstring> compilerFlags = m_settings->getCompilerFlags();
utility::append(compilerFlags, m_settings->getCompilerFlags());
}
const std::set<FilePath> indexedHeaderPaths = utility::toSet(m_settings->getIndexedHeaderPathsExpandedAndAbsolute());
const std::set<FilePathFilter> excludeFilters = utility::toSet(m_settings->getExcludeFiltersExpandedAndAbsolute());
@@ -126,6 +127,10 @@ std::shared_ptr<IndexerCommandProvider> SourceGroupCxxCdb::getIndexerCommandProv
{
sourcePath = FilePath(utility::decodeFromUtf8(command.Directory + '/' + command.Filename)).makeCanonical();
}
if (!sourcePath.isAbsolute())
{
sourcePath = cdbPath.getParentDirectory().getConcatenated(sourcePath).makeCanonical();
}
if (filesToIndex.find(sourcePath) != filesToIndex.end() &&
sourceFilePaths.find(sourcePath) != sourceFilePaths.end())
@@ -144,8 +149,6 @@ std::shared_ptr<IndexerCommandProvider> SourceGroupCxxCdb::getIndexerCommandProv
excludeFilters,
std::set<FilePathFilter>(),
FilePath(utility::decodeFromUtf8(command.Directory)),
systemHeaderSearchPaths,
frameworkSearchPaths,
mergedCompilerFlags
));
}
+41 -38
View File
@@ -70,7 +70,6 @@ std::shared_ptr<IndexerCommandProvider> SourceGroupCxxEmpty::getIndexerCommandPr
{
std::shared_ptr<ApplicationSettings> appSettings = ApplicationSettings::getInstance();
std::vector<FilePath> systemHeaderSearchPaths;
std::set<FilePath> indexedPaths;
std::set<FilePathFilter> excludeFilters;
@@ -90,22 +89,6 @@ std::shared_ptr<IndexerCommandProvider> SourceGroupCxxEmpty::getIndexerCommandPr
targetFlag = settings->getTargetFlag();
}
// Add the source paths as HeaderSearchPaths as well, so clang will also look here when searching include files.
for (const FilePath& sourcePath: indexedPaths)
{
if (sourcePath.isDirectory())
{
systemHeaderSearchPaths.push_back(sourcePath);
}
}
utility::append(systemHeaderSearchPaths, m_settings->getHeaderSearchPathsExpandedAndAbsolute());
utility::append(systemHeaderSearchPaths, appSettings->getHeaderSearchPathsExpanded());
std::vector<FilePath> frameworkSearchPaths;
utility::append(frameworkSearchPaths, m_settings->getFrameworkSearchPathsExpandedAndAbsolute());
utility::append(frameworkSearchPaths, appSettings->getFrameworkSearchPathsExpanded());
std::vector<std::wstring> compilerFlags;
{
if (!targetFlag.empty())
@@ -114,32 +97,54 @@ std::shared_ptr<IndexerCommandProvider> SourceGroupCxxEmpty::getIndexerCommandPr
}
}
{
std::wstring languageStandard = SourceGroupSettingsWithCppStandard::getDefaultCppStandardStatic();
if (std::shared_ptr<SourceGroupSettingsWithCStandard> cSettings =
std::dynamic_pointer_cast<SourceGroupSettingsWithCStandard>(m_settings))
{
languageStandard = cSettings->getCStandard();
}
else if (std::shared_ptr<SourceGroupSettingsWithCppStandard> cppSettings =
std::dynamic_pointer_cast<SourceGroupSettingsWithCppStandard>(m_settings))
{
languageStandard = cppSettings->getCppStandard();
}
else
{
LOG_ERROR(L"Source group doesn't specify language standard. Falling back to \"" + languageStandard + L"\".");
}
compilerFlags.push_back(IndexerCommandCxx::getCompilerFlagLanguageStandard(languageStandard));
}
if (std::dynamic_pointer_cast<SourceGroupSettingsCppEmpty>(m_settings))
{
compilerFlags.push_back(L"-x");
compilerFlags.push_back(L"c++");
}
{
// Add the source paths as HeaderSearchPaths as well, so clang will also look here when searching include files.
std::vector<FilePath> indexedDirectoryPaths;
for (const FilePath& sourcePath : indexedPaths)
{
if (sourcePath.isDirectory())
{
indexedDirectoryPaths.push_back(sourcePath);
}
}
utility::append(compilerFlags, IndexerCommandCxx::getCompilerFlagsForSystemHeaderSearchPaths(indexedDirectoryPaths));
utility::append(compilerFlags, IndexerCommandCxx::getCompilerFlagsForSystemHeaderSearchPaths(m_settings->getHeaderSearchPathsExpandedAndAbsolute()));
utility::append(compilerFlags, IndexerCommandCxx::getCompilerFlagsForSystemHeaderSearchPaths(appSettings->getHeaderSearchPathsExpanded()));
}
{
utility::append(compilerFlags, IndexerCommandCxx::getCompilerFlagsForFrameworkSearchPaths(m_settings->getFrameworkSearchPathsExpandedAndAbsolute()));
utility::append(compilerFlags, IndexerCommandCxx::getCompilerFlagsForFrameworkSearchPaths(appSettings->getFrameworkSearchPathsExpanded()));
}
utility::append(compilerFlags, m_settings->getCompilerFlags());
std::wstring languageStandard = SourceGroupSettingsWithCppStandard::getDefaultCppStandardStatic();
if (std::shared_ptr<SourceGroupSettingsWithCStandard> cSettings =
std::dynamic_pointer_cast<SourceGroupSettingsWithCStandard>(m_settings))
{
languageStandard = cSettings->getCStandard();
}
else if (std::shared_ptr<SourceGroupSettingsWithCppStandard> cppSettings =
std::dynamic_pointer_cast<SourceGroupSettingsWithCppStandard>(m_settings))
{
languageStandard = cppSettings->getCppStandard();
}
else
{
LOG_ERROR(L"Source group doesn't specify language standard. Falling back to \"" + languageStandard + L"\".");
}
compilerFlags.push_back(L"-std=" + languageStandard);
std::shared_ptr<CxxIndexerCommandProvider> provider = std::make_shared<CxxIndexerCommandProvider>();
for (const FilePath& sourcePath: getAllSourceFilePaths())
{
@@ -151,9 +156,7 @@ std::shared_ptr<IndexerCommandProvider> SourceGroupCxxEmpty::getIndexerCommandPr
excludeFilters,
std::set<FilePathFilter>(),
m_settings->getProjectDirectoryPath(),
systemHeaderSearchPaths,
frameworkSearchPaths,
utility::concat(compilerFlags, { sourcePath.wstr() })
utility::concat(compilerFlags, sourcePath.wstr())
));
}
}
@@ -206,8 +206,6 @@ namespace Codeblocks
const std::set<FilePathFilter> excludeFilters = utility::toSet(sourceGroupSettings->getExcludeFiltersExpandedAndAbsolute());
const std::vector<std::wstring> compilerFlags = sourceGroupSettings->getCompilerFlags();
const std::vector<FilePath> systemHeaderSearchPaths = utility::concat(
sourceGroupSettings->getHeaderSearchPathsExpandedAndAbsolute(),
appSettings->getHeaderSearchPathsExpanded()
@@ -219,25 +217,25 @@ namespace Codeblocks
);
OrderedCache<std::wstring, std::vector<std::wstring>> optionsCache([&](const std::wstring& targetName) {
std::vector<std::wstring> compilerFlags;
for (std::shared_ptr<Target> target : m_targets)
{
if (target->getTitle() == targetName)
{
return target->getCompiler()->getOptions();
compilerFlags = utility::concat(
IndexerCommandCxx::getCompilerFlagsForSystemHeaderSearchPaths(
utility::convert<std::wstring, FilePath>(target->getCompiler()->getDirectories())
),
target->getCompiler()->getOptions()
);
break;
}
}
return std::vector<std::wstring>();
});
OrderedCache<std::wstring, std::vector<FilePath>> headerSearchPathsCache([&](const std::wstring& targetName) {
for (std::shared_ptr<Target> target : m_targets)
{
if (target->getTitle() == targetName)
{
return utility::convert<std::wstring, FilePath>(target->getCompiler()->getDirectories());
}
}
return std::vector<FilePath>();
utility::append(compilerFlags, IndexerCommandCxx::getCompilerFlagsForSystemHeaderSearchPaths(systemHeaderSearchPaths));
utility::append(compilerFlags, IndexerCommandCxx::getCompilerFlagsForFrameworkSearchPaths(frameworkSearchPaths));
utility::append(compilerFlags, sourceGroupSettings->getCompilerFlags());
return compilerFlags;
});
std::vector<std::shared_ptr<IndexerCommandCxx>> indexerCommands;
@@ -267,8 +265,6 @@ namespace Codeblocks
continue;
}
const std::vector<std::wstring> compilerFlagsWithStandard = utility::concat(compilerFlags, { L"-std=" + languageStandard });
for (const std::wstring& targetName : unit->getTargetNames())
{
indexerCommands.push_back(std::make_shared<IndexerCommandCxx>(
@@ -277,9 +273,10 @@ namespace Codeblocks
excludeFilters,
std::set<FilePathFilter>(),
sourceGroupSettings->getCodeblocksProjectPathExpandedAndAbsolute().getParentDirectory(),
utility::concat(systemHeaderSearchPaths, headerSearchPathsCache.getValue(targetName)),
frameworkSearchPaths,
utility::concat(utility::concat(optionsCache.getValue(targetName), compilerFlagsWithStandard), { filePath.wstr() })
utility::concat(
optionsCache.getValue(targetName),
{ IndexerCommandCxx::getCompilerFlagLanguageStandard(languageStandard), filePath.wstr() }
)
));
}
}
+12 -12
View File
@@ -39,18 +39,18 @@ namespace utility
std::shared_ptr<JavaEnvironment> javaEnvironment = JavaEnvironmentFactory::getInstance()->createEnvironment();
bool success = javaEnvironment->callStaticVoidMethod(
"com/sourcetrail/gradle/InfoRetriever",
"copyCompileLibs",
"com/sourcetrail/gradle/InfoRetriever",
"copyCompileLibs",
utility::encodeToUtf8(projectDirectoryPath.wstr()),
utility::encodeToUtf8(gradleInitScriptPath.wstr()),
utility::encodeToUtf8(outputDirectoryPath.wstr())
);
if (success && addTestDependencies)
{
success = javaEnvironment->callStaticVoidMethod(
"com/sourcetrail/gradle/InfoRetriever",
"copyTestCompileLibs",
"copyTestCompileLibs",
utility::encodeToUtf8(projectDirectoryPath.wstr()),
utility::encodeToUtf8(gradleInitScriptPath.wstr()),
utility::encodeToUtf8(outputDirectoryPath.wstr())
@@ -73,9 +73,9 @@ namespace utility
{
std::string output = "";
javaEnvironment->callStaticStringMethod(
"com/sourcetrail/gradle/InfoRetriever",
"getMainSrcDirs",
output,
"com/sourcetrail/gradle/InfoRetriever",
"getMainSrcDirs",
output,
utility::encodeToUtf8(projectDirectoryPath.wstr()),
utility::encodeToUtf8(gradleInitScriptPath.wstr())
);
@@ -84,7 +84,7 @@ namespace utility
{
// TODO: move error handling to caller of this function
const std::wstring dialogMessage =
L"The following error occurred while executing a Gradle command:\n\n" +
L"The following error occurred while executing a Gradle command:\n\n" +
utility::decodeFromUtf8(utility::replace(output, "\r\n", "\n"));
MessageStatus(dialogMessage, true, false).dispatch();
Application::getInstance()->handleDialog(dialogMessage);
@@ -102,18 +102,18 @@ namespace utility
{
std::string output = "";
javaEnvironment->callStaticStringMethod(
"com/sourcetrail/gradle/InfoRetriever",
"getTestSrcDirs",
"com/sourcetrail/gradle/InfoRetriever",
"getTestSrcDirs",
output,
utility::encodeToUtf8(projectDirectoryPath.wstr()),
utility::encodeToUtf8(gradleInitScriptPath.wstr())
);
if (utility::isPrefix<std::string>("[ERROR]", utility::trim(output)))
{
// TODO: move error handling to caller of this function
const std::wstring dialogMessage =
L"The following error occurred while executing a Gradle command:\n\n" +
L"The following error occurred while executing a Gradle command:\n\n" +
utility::decodeFromUtf8(utility::replace(output, "\r\n", "\n"));
MessageStatus(dialogMessage, true, false).dispatch();
Application::getInstance()->handleDialog(dialogMessage);
+1 -1
View File
@@ -31,7 +31,7 @@ add_files(
SettingsMigratorTestSuite.h
SettingsTestSuite.h
SharedMemoryTestSuite.h
SonargraphProjectTestSuite.h
SourceGroupTestSuite.h
SourceLocationCollectionTestSuite.h
SqliteBookmarkStorageTestSuite.h
SqliteIndexStorageTestSuite.h
+12 -3
View File
@@ -157,6 +157,17 @@ private:
const std::set<FilePathFilter> includedFilters = {};
const FilePath workingDirectory(L".");
std::vector<std::wstring> compilerFlags;
utility::append(compilerFlags, IndexerCommandCxx::getCompilerFlagsForSystemHeaderSearchPaths(
utility::concat(std::vector<FilePath> { projectDataSrcRoot }, ApplicationSettings::getInstance()->getHeaderSearchPathsExpanded())
));
utility::append(compilerFlags, IndexerCommandCxx::getCompilerFlagsForFrameworkSearchPaths(
ApplicationSettings::getInstance()->getFrameworkSearchPathsExpanded()
));
compilerFlags.emplace_back(L"--target=x86_64-pc-windows-msvc");
compilerFlags.emplace_back(L"-std=c++1z");
compilerFlags.emplace_back(sourceFilePath.wstr());
std::shared_ptr<FileRegister> fileRegister = std::make_shared<FileRegister>(
sourceFilePath,
indexedPaths,
@@ -173,9 +184,7 @@ private:
excludedFilters,
includedFilters,
workingDirectory,
utility::concat(std::vector<FilePath> { projectDataSrcRoot }, ApplicationSettings::getInstance()->getHeaderSearchPathsExpanded()),
ApplicationSettings::getInstance()->getFrameworkSearchPathsExpanded(),
std::vector<std::wstring> { L"--target=x86_64-pc-windows-msvc", L"-std=c++1z", sourceFilePath.wstr() }
compilerFlags
);
TimeStamp startTime = TimeStamp::now();
-2
View File
@@ -4124,8 +4124,6 @@ public:
excludeFilters,
includeFilters,
workingDirectory,
std::vector<FilePath>(),
std::vector<FilePath>(),
std::vector<std::wstring> { L"--target=x86_64-pc-windows-msvc", L"-std=c++1z", sourceFilePath.wstr() }
);
-205
View File
@@ -1,205 +0,0 @@
#include "cxxtest/TestSuite.h"
#include <fstream>
#include "data/indexer/IndexerCommandCxx.h"
#include "data/indexer/IndexerCommandJava.h"
#include "project/SourceGroupJavaSonargraph.h"
#include "settings/SourceGroupSettingsCxxSonargraph.h"
#include "settings/SourceGroupSettingsJavaSonargraph.h"
#include "settings/ProjectSettings.h"
#include "settings/ApplicationSettings.h"
#include "utility/sonargraph/SonargraphProject.h"
#include "utility/text/TextAccess.h"
#include "utility/utilityString.h"
class SonargraphProjectTestSuite: public CxxTest::TestSuite
{
public:
static const bool s_updateExpectedOutput = false;
void test_sonargraph_project_with_cmake_json_modules_generates_expected_output()
{
const std::wstring projectName = L"CxxCmakeJsonModules";
ProjectSettings projectSettings;
std::shared_ptr<SourceGroupSettingsCxxSonargraph> sourceGroupSettings = std::make_shared<SourceGroupSettingsCxxSonargraph>("fake_id", &projectSettings);
sourceGroupSettings->setIndexedHeaderPaths({ FilePath(L"test/indexed/header/path") });
std::shared_ptr<ApplicationSettings> applicationSettings = std::make_shared<ApplicationSettings>();
applicationSettings->setHeaderSearchPaths({ FilePath(L"test/header/search/path") });
applicationSettings->setFrameworkSearchPaths({ FilePath(L"test/framework/search/path") });
generateAndCompareExpectedOutputForSonargraphProject(projectName, sourceGroupSettings, applicationSettings);
}
void test_sonargraph_project_with_cpp_manual_modules_generates_expected_output()
{
const std::wstring projectName = L"CxxCppManualModules";
ProjectSettings projectSettings;
std::shared_ptr<SourceGroupSettingsCxxSonargraph> sourceGroupSettings = std::make_shared<SourceGroupSettingsCxxSonargraph>("fake_id", &projectSettings);
sourceGroupSettings->setIndexedHeaderPaths({ FilePath(L"test/indexed/header/path") });
std::shared_ptr<ApplicationSettings> applicationSettings = std::make_shared<ApplicationSettings>();
applicationSettings->setHeaderSearchPaths({ FilePath(L"test/header/search/path") });
applicationSettings->setFrameworkSearchPaths({ FilePath(L"test/framework/search/path") });
generateAndCompareExpectedOutputForSonargraphProject(projectName, sourceGroupSettings, applicationSettings);
}
void test_sonargraph_project_with_java_modules_generates_expected_output()
{
const std::wstring projectName = L"JavaModules";
ProjectSettings projectSettings;
std::shared_ptr<SourceGroupSettingsJavaSonargraph> sourceGroupSettings =
std::make_shared<SourceGroupSettingsJavaSonargraph>("fake_id", &projectSettings);
sourceGroupSettings->setUseJreSystemLibrary(true);
sourceGroupSettings->setClasspath({
FilePath(L"test/classpath/file.jar"), FilePath(L"test/classpath/dir")
});
std::shared_ptr<ApplicationSettings> applicationSettings = std::make_shared<ApplicationSettings>();
applicationSettings->setJreSystemLibraryPaths({ FilePath(L"test/jre/system/library/path.jar") });
generateAndCompareExpectedOutputForSonargraphProject(projectName, sourceGroupSettings, applicationSettings);
}
void test_sonargraph_project_with_cpp_modules_does_not_generate_output_for_java_sourcegroup()
{
const std::wstring projectName = L"CxxCmakeJsonModules";
ProjectSettings projectSettings;
std::shared_ptr<SourceGroupSettings> sourceGroupSettings = std::make_shared<SourceGroupSettingsJavaSonargraph>("fake_id", &projectSettings);
std::shared_ptr<ApplicationSettings> applicationSettings = std::make_shared<ApplicationSettings>();
std::shared_ptr<TextAccess> output = generateExpectedOutputForSonargraphProject(projectName, sourceGroupSettings, applicationSettings);
TS_ASSERT_EQUALS(0, output->getLineCount());
}
void test_sonargraph_project_with_java_modules_does_not_generate_output_for_cpp_sourcegroup()
{
const std::wstring projectName = L"JavaModules";
ProjectSettings projectSettings;
std::shared_ptr<SourceGroupSettings> sourceGroupSettings = std::make_shared<SourceGroupSettingsCxxSonargraph>("fake_id", &projectSettings);
std::shared_ptr<ApplicationSettings> applicationSettings = std::make_shared<ApplicationSettings>();
std::shared_ptr<TextAccess> output = generateExpectedOutputForSonargraphProject(projectName, sourceGroupSettings, applicationSettings);
TS_ASSERT_EQUALS(0, output->getLineCount());
}
void generateAndCompareExpectedOutputForSonargraphProject(
std::wstring projectName,
std::shared_ptr<const SourceGroupSettings> sourceGroupSettings,
std::shared_ptr<const ApplicationSettings> applicationSettings)
{
const FilePath projectDataRoot = FilePath(L"data/SonargraphProjectTestSuite/" + projectName).makeAbsolute();
const FilePath projectDataExpectedOutputRoot = projectDataRoot.getConcatenated(L"expected_output");
std::shared_ptr<TextAccess> output = generateExpectedOutputForSonargraphProject(projectName, sourceGroupSettings, applicationSettings);
FilePath expectedOutputFilePath = projectDataExpectedOutputRoot.getConcatenated(L"output.txt");
if (s_updateExpectedOutput || !expectedOutputFilePath.exists())
{
std::ofstream expectedOutputFile;
expectedOutputFile.open(expectedOutputFilePath.str());
expectedOutputFile << output->getText();
expectedOutputFile.close();
}
else
{
std::shared_ptr<TextAccess> expectedOutput = TextAccess::createFromFile(expectedOutputFilePath);
TSM_ASSERT_EQUALS(L"Output does not match the expected line count for project \"" + projectName + L"\".", expectedOutput->getLineCount(), output->getLineCount());
if (expectedOutput->getLineCount() == output->getLineCount())
{
for (size_t i = 1; i <= expectedOutput->getLineCount(); i++)
{
TS_ASSERT_EQUALS(expectedOutput->getLine(i), output->getLine(i));
}
}
}
}
std::shared_ptr<TextAccess> generateExpectedOutputForSonargraphProject(
std::wstring projectName,
std::shared_ptr<const SourceGroupSettings> sourceGroupSettings,
std::shared_ptr<const ApplicationSettings> applicationSettings)
{
const FilePath projectDataRoot = FilePath(L"data/SonargraphProjectTestSuite/" + projectName).makeAbsolute();
const FilePath projectDataSrcRoot = projectDataRoot.getConcatenated(L"src/sonargraph");
std::shared_ptr<Sonargraph::Project> project = Sonargraph::Project::load(projectDataSrcRoot.getConcatenated(L"system.sonargraph"), sourceGroupSettings->getLanguage());
TS_ASSERT(project.use_count() > 0);
std::vector<std::shared_ptr<IndexerCommand>> indexerCommands = project->getIndexerCommands(sourceGroupSettings, applicationSettings);
std::wstring outputString;
for (std::shared_ptr<IndexerCommand> indexerCommand : indexerCommands)
{
outputString += indexerCommandToString(indexerCommand, projectDataRoot);
}
return TextAccess::createFromString(utility::encodeToUtf8(outputString));
}
std::wstring indexerCommandToString(std::shared_ptr<IndexerCommand> indexerCommand, const FilePath& baseDirectory)
{
if (indexerCommand)
{
if (std::shared_ptr<const IndexerCommandCxx> indexerCommandCxx = std::dynamic_pointer_cast<const IndexerCommandCxx>(indexerCommand))
{
return indexerCommandCxxToString(indexerCommandCxx, baseDirectory);
}
if (std::shared_ptr<const IndexerCommandJava> indexerCommandJava = std::dynamic_pointer_cast<const IndexerCommandJava>(indexerCommand))
{
return indexerCommandJavaToString(indexerCommandJava, baseDirectory);
}
return L"Unsupported indexer command type: " + utility::decodeFromUtf8(indexerCommandTypeToString(indexerCommand->getIndexerCommandType()));
}
return L"No IndexerCommand provided.";
}
std::wstring indexerCommandCxxToString(std::shared_ptr<const IndexerCommandCxx> indexerCommand, const FilePath& baseDirectory)
{
std::wstring result;
result += L"SourceFilePath: \"" + indexerCommand->getSourceFilePath().getRelativeTo(baseDirectory).wstr() + L"\"\n";
for (const FilePath& indexedPath : indexerCommand->getIndexedPaths())
{
result += L"\tIndexedPath: \"" + indexedPath.getRelativeTo(baseDirectory).wstr() + L"\"\n";
}
for (std::wstring compilerFlag : indexerCommand->getCompilerFlags())
{
FilePath flagAsPath(compilerFlag);
if (flagAsPath.exists())
{
compilerFlag = flagAsPath.getRelativeTo(baseDirectory).wstr();
}
result += L"\tCompilerFlag: \"" + compilerFlag + L"\"\n";
}
for (const FilePath& headerSearchPath : indexerCommand->getSystemHeaderSearchPaths())
{
result += L"\tHeaderSearchPath: \"" + headerSearchPath.getRelativeTo(baseDirectory).wstr() + L"\"\n";
}
for (const FilePath& frameworkSearchPath : indexerCommand->getFrameworkSearchPaths())
{
result += L"\tFrameworkSearchPath: \"" + frameworkSearchPath.wstr() + L"\"\n";
}
return result;
}
std::wstring indexerCommandJavaToString(std::shared_ptr<const IndexerCommandJava> indexerCommand, const FilePath& baseDirectory)
{
std::wstring result;
result += L"SourceFilePath: \"" + indexerCommand->getSourceFilePath().getRelativeTo(baseDirectory).wstr() + L"\"\n";
result += L"\tLanguageStandard: \"" + indexerCommand->getLanguageStandard() + L"\"\n";
for (const FilePath& classPathItem : indexerCommand->getClassPath())
{
result += L"\tClassPathItem: \"" + classPathItem.getRelativeTo(baseDirectory).wstr() + L"\"\n";
}
return result;
}
};
+587
View File
@@ -0,0 +1,587 @@
#include "cxxtest/TestSuite.h"
#include <fstream>
#include "data/indexer/IndexerCommandCxx.h"
#include "data/indexer/IndexerCommandJava.h"
#include "data/parser/java/JavaEnvironmentFactory.h"
#include "project/SourceGroupCxxEmpty.h"
#include "project/SourceGroupCxxCdb.h"
#include "project/SourceGroupCxxCodeblocks.h"
#include "project/SourceGroupCxxSonargraph.h"
#include "project/SourceGroupJavaEmpty.h"
#include "project/SourceGroupJavaGradle.h"
#include "project/SourceGroupJavaMaven.h"
#include "project/SourceGroupJavaSonargraph.h"
#include "settings/SourceGroupSettingsCEmpty.h"
#include "settings/SourceGroupSettingsCppEmpty.h"
#include "settings/SourceGroupSettingsCxxCdb.h"
#include "settings/SourceGroupSettingsCxxCodeblocks.h"
#include "settings/SourceGroupSettingsCxxSonargraph.h"
#include "settings/SourceGroupSettingsJavaEmpty.h"
#include "settings/SourceGroupSettingsJavaGradle.h"
#include "settings/SourceGroupSettingsJavaMaven.h"
#include "settings/SourceGroupSettingsJavaSonargraph.h"
#include "settings/ProjectSettings.h"
#include "settings/ApplicationSettings.h"
#include "utility/file/FileSystem.h"
#include "utility/text/TextAccess.h"
#include "utility/AppPath.h"
#include "utility/utilityJava.h"
#include "utility/utilityPathDetection.h"
#include "utility/utilityString.h"
#include "utility/Version.h"
#include "Application.h"
class SourceGroupTestSuite: public CxxTest::TestSuite
{
public:
static const bool s_updateExpectedOutput = false;
void test_finds_all_jar_dependencies()
{
for (const std::wstring& jarName : utility::getRequiredJarNames())
{
FilePath jarPath = FilePath(L"../app/data/java/lib/").concatenate(jarName);
TSM_ASSERT(L"Jar dependency path does not exist: " + jarPath.wstr(), jarPath.exists());
}
}
void test_can_setup_environment_factory()
{
std::vector<FilePath> javaPaths = utility::getJavaRuntimePathDetector()->getPaths();
if (!javaPaths.empty())
{
ApplicationSettings::getInstance()->setJavaPath(javaPaths[0]);
}
const std::string errorString = setupJavaEnvironmentFactory();
TS_ASSERT_EQUALS("", errorString);
// if this one fails, maybe your java_path in the test settings is wrong.
TS_ASSERT_LESS_THAN_EQUALS(1, JavaEnvironmentFactory::getInstance().use_count());
}
void test_can_create_application_instance()
{
// required to query in SourceGroup for dialog view... this is not a very elegant solution. should be refactored to pass dialog view to SourceGroup on creation.
Application::createInstance(Version(), nullptr, nullptr);
TS_ASSERT_LESS_THAN_EQUALS(1, Application::getInstance().use_count());
}
void test_source_group_cxx_c_empty_generates_expected_output()
{
const std::wstring projectName = L"cxx_c_empty";
ProjectSettings projectSettings;
projectSettings.setProjectFilePath(L"non_existent_project", getInputDirectoryPath(projectName));
std::shared_ptr<SourceGroupSettingsCEmpty> sourceGroupSettings = std::make_shared<SourceGroupSettingsCEmpty>("fake_id", &projectSettings);
sourceGroupSettings->setSourcePaths({ getInputDirectoryPath(projectName).concatenate(L"src") });
sourceGroupSettings->setSourceExtensions({ L".c" });
sourceGroupSettings->setExcludeFilterStrings({ L"**/excluded/**" });
sourceGroupSettings->setTargetOptionsEnabled(true);
sourceGroupSettings->setTargetArch(L"test_arch");
sourceGroupSettings->setTargetVendor(L"test_vendor");
sourceGroupSettings->setTargetSys(L"test_sys");
sourceGroupSettings->setTargetAbi(L"test_abi");
sourceGroupSettings->setCStandard(L"c11");
sourceGroupSettings->setHeaderSearchPaths({ getInputDirectoryPath(projectName).concatenate(L"header_search/local") });
sourceGroupSettings->setFrameworkSearchPaths({ getInputDirectoryPath(projectName).concatenate(L"framework_search/local") });
sourceGroupSettings->setCompilerFlags({ L"-local-flag" });
std::shared_ptr<ApplicationSettings> applicationSettings = ApplicationSettings::getInstance();
std::vector<FilePath> storedHeaderSearchPaths = applicationSettings->getHeaderSearchPaths();
std::vector<FilePath> storedFrameworkSearchPaths = applicationSettings->getFrameworkSearchPaths();
applicationSettings->setHeaderSearchPaths({ FilePath(L"test/header/search/path") });
applicationSettings->setFrameworkSearchPaths({ FilePath(L"test/framework/search/path") });
generateAndCompareExpectedOutput(projectName, std::make_shared<SourceGroupCxxEmpty>(sourceGroupSettings));
applicationSettings->setHeaderSearchPaths(storedHeaderSearchPaths);
applicationSettings->setFrameworkSearchPaths(storedFrameworkSearchPaths);
}
void test_source_group_cxx_cpp_empty_generates_expected_output()
{
const std::wstring projectName = L"cxx_cpp_empty";
ProjectSettings projectSettings;
projectSettings.setProjectFilePath(L"non_existent_project", getInputDirectoryPath(projectName));
std::shared_ptr<SourceGroupSettingsCppEmpty> sourceGroupSettings = std::make_shared<SourceGroupSettingsCppEmpty>("fake_id", &projectSettings);
sourceGroupSettings->setSourcePaths({ getInputDirectoryPath(projectName).concatenate(L"/src") });
sourceGroupSettings->setSourceExtensions({ L".cpp" });
sourceGroupSettings->setExcludeFilterStrings({ L"**/excluded/**" });
sourceGroupSettings->setTargetOptionsEnabled(true);
sourceGroupSettings->setTargetArch(L"test_arch");
sourceGroupSettings->setTargetVendor(L"test_vendor");
sourceGroupSettings->setTargetSys(L"test_sys");
sourceGroupSettings->setTargetAbi(L"test_abi");
sourceGroupSettings->setCppStandard(L"c++11");
sourceGroupSettings->setHeaderSearchPaths({ getInputDirectoryPath(projectName).concatenate(L"header_search/local") });
sourceGroupSettings->setFrameworkSearchPaths({ getInputDirectoryPath(projectName).concatenate(L"framework_search/local") });
sourceGroupSettings->setCompilerFlags({ L"-local-flag" });
std::shared_ptr<ApplicationSettings> applicationSettings = ApplicationSettings::getInstance();
std::vector<FilePath> storedHeaderSearchPaths = applicationSettings->getHeaderSearchPaths();
std::vector<FilePath> storedFrameworkSearchPaths = applicationSettings->getFrameworkSearchPaths();
applicationSettings->setHeaderSearchPaths({ FilePath(L"test/header/search/path") });
applicationSettings->setFrameworkSearchPaths({ FilePath(L"test/framework/search/path") });
generateAndCompareExpectedOutput(projectName, std::make_shared<SourceGroupCxxEmpty>(sourceGroupSettings));
applicationSettings->setHeaderSearchPaths(storedHeaderSearchPaths);
applicationSettings->setFrameworkSearchPaths(storedFrameworkSearchPaths);
}
void test_source_group_cxx_codeblocks_generates_expected_output()
{
const std::wstring projectName = L"cxx_codeblocks";
const FilePath cbpPath = getInputDirectoryPath(projectName).concatenate(L"project.cbp");
const FilePath sourceCbpPath = getInputDirectoryPath(projectName).concatenate(L"project.cbp.in");
FileSystem::remove(cbpPath);
{
std::ofstream fileStream;
fileStream.open(cbpPath.str(), std::ios::app);
fileStream << utility::replace(
TextAccess::createFromFile(sourceCbpPath)->getText(), "<source_path>", getInputDirectoryPath(projectName).concatenate(L"src").getAbsolute().str()
);
fileStream.close();
}
ProjectSettings projectSettings;
projectSettings.setProjectFilePath(L"non_existent_project", getInputDirectoryPath(projectName));
std::shared_ptr<SourceGroupSettingsCxxCodeblocks> sourceGroupSettings = std::make_shared<SourceGroupSettingsCxxCodeblocks>("fake_id", &projectSettings);
sourceGroupSettings->setCodeblocksProjectPath(cbpPath);
sourceGroupSettings->setCppStandard(L"c++11");
sourceGroupSettings->setCStandard(L"c11");
sourceGroupSettings->setExcludeFilterStrings({ L"**/excluded/**" });
sourceGroupSettings->setIndexedHeaderPaths({ FilePath(L"test/indexed/header/path") });
sourceGroupSettings->setSourceExtensions({ L".cpp", L".c" });
sourceGroupSettings->setHeaderSearchPaths({ getInputDirectoryPath(projectName).concatenate(L"header_search/local") });
sourceGroupSettings->setFrameworkSearchPaths({ getInputDirectoryPath(projectName).concatenate(L"framework_search/local") });
sourceGroupSettings->setCompilerFlags({ L"-local-flag" });
std::shared_ptr<ApplicationSettings> applicationSettings = ApplicationSettings::getInstance();
std::vector<FilePath> storedHeaderSearchPaths = applicationSettings->getHeaderSearchPaths();
std::vector<FilePath> storedFrameworkSearchPaths = applicationSettings->getFrameworkSearchPaths();
applicationSettings->setHeaderSearchPaths({ FilePath(L"test/header/search/path") });
applicationSettings->setFrameworkSearchPaths({ FilePath(L"test/framework/search/path") });
generateAndCompareExpectedOutput(projectName, std::make_shared<SourceGroupCxxCodeblocks>(sourceGroupSettings));
applicationSettings->setHeaderSearchPaths(storedHeaderSearchPaths);
applicationSettings->setFrameworkSearchPaths(storedFrameworkSearchPaths);
FileSystem::remove(cbpPath);
}
void test_source_group_cxx_cdb_generates_expected_output()
{
const std::wstring projectName = L"cxx_cdb";
ProjectSettings projectSettings;
projectSettings.setProjectFilePath(L"non_existent_project", getInputDirectoryPath(projectName));
std::shared_ptr<SourceGroupSettingsCxxCdb> sourceGroupSettings = std::make_shared<SourceGroupSettingsCxxCdb>("fake_id", &projectSettings);
sourceGroupSettings->setIndexedHeaderPaths({ FilePath(L"test/indexed/header/path") });
sourceGroupSettings->setCompilationDatabasePath(getInputDirectoryPath(projectName).concatenate(L"compile_commands.json"));
sourceGroupSettings->setExcludeFilterStrings({ L"**/excluded/**" });
sourceGroupSettings->setHeaderSearchPaths({ getInputDirectoryPath(projectName).concatenate(L"header_search/local") });
sourceGroupSettings->setFrameworkSearchPaths({ getInputDirectoryPath(projectName).concatenate(L"framework_search/local") });
sourceGroupSettings->setCompilerFlags({ L"-local-flag" });
std::shared_ptr<ApplicationSettings> applicationSettings = ApplicationSettings::getInstance();
std::vector<FilePath> storedHeaderSearchPaths = applicationSettings->getHeaderSearchPaths();
std::vector<FilePath> storedFrameworkSearchPaths = applicationSettings->getFrameworkSearchPaths();
applicationSettings->setHeaderSearchPaths({ FilePath(L"test/header/search/path") });
applicationSettings->setFrameworkSearchPaths({ FilePath(L"test/framework/search/path") });
generateAndCompareExpectedOutput(projectName, std::make_shared<SourceGroupCxxCdb>(sourceGroupSettings));
applicationSettings->setHeaderSearchPaths(storedHeaderSearchPaths);
applicationSettings->setFrameworkSearchPaths(storedFrameworkSearchPaths);
}
void test_source_group_cxx_sonargraph_with_cmake_json_modules_generates_expected_output()
{
const std::wstring projectName = L"cxx_sonargraph_cmake_json";
ProjectSettings projectSettings;
projectSettings.setProjectFilePath(L"non_existent_project", getInputDirectoryPath(projectName));
std::shared_ptr<SourceGroupSettingsCxxSonargraph> sourceGroupSettings = std::make_shared<SourceGroupSettingsCxxSonargraph>("fake_id", &projectSettings);
sourceGroupSettings->setIndexedHeaderPaths({ FilePath(L"test/indexed/header/path") });
sourceGroupSettings->setSonargraphProjectPath(getInputDirectoryPath(projectName).concatenate(L"sonargraph/system.sonargraph"));
std::shared_ptr<ApplicationSettings> applicationSettings = ApplicationSettings::getInstance();
std::vector<FilePath> storedHeaderSearchPaths = applicationSettings->getHeaderSearchPaths();
std::vector<FilePath> storedFrameworkSearchPaths = applicationSettings->getFrameworkSearchPaths();
applicationSettings->setHeaderSearchPaths({ FilePath(L"test/header/search/path") });
applicationSettings->setFrameworkSearchPaths({ FilePath(L"test/framework/search/path") });
generateAndCompareExpectedOutput(projectName, std::make_shared<SourceGroupCxxSonargraph>(sourceGroupSettings));
applicationSettings->setHeaderSearchPaths(storedHeaderSearchPaths);
applicationSettings->setFrameworkSearchPaths(storedFrameworkSearchPaths);
}
void test_source_group_cxx_sonargraph_with_cpp_manual_modules_generates_expected_output()
{
const std::wstring projectName = L"cxx_sonargraph_cpp_manual";
ProjectSettings projectSettings;
projectSettings.setProjectFilePath(L"non_existent_project", getInputDirectoryPath(projectName));
std::shared_ptr<SourceGroupSettingsCxxSonargraph> sourceGroupSettings = std::make_shared<SourceGroupSettingsCxxSonargraph>("fake_id", &projectSettings);
sourceGroupSettings->setIndexedHeaderPaths({ FilePath(L"test/indexed/header/path") });
sourceGroupSettings->setSonargraphProjectPath(getInputDirectoryPath(projectName).concatenate(L"/sonargraph/system.sonargraph"));
std::shared_ptr<ApplicationSettings> applicationSettings = ApplicationSettings::getInstance();
std::vector<FilePath> storedHeaderSearchPaths = applicationSettings->getHeaderSearchPaths();
std::vector<FilePath> storedFrameworkSearchPaths = applicationSettings->getFrameworkSearchPaths();
applicationSettings->setHeaderSearchPaths({ FilePath(L"test/header/search/path") });
applicationSettings->setFrameworkSearchPaths({ FilePath(L"test/framework/search/path") });
generateAndCompareExpectedOutput(projectName, std::make_shared<SourceGroupCxxSonargraph>(sourceGroupSettings));
applicationSettings->setHeaderSearchPaths(storedHeaderSearchPaths);
applicationSettings->setFrameworkSearchPaths(storedFrameworkSearchPaths);
}
void test_sourcegroup_java_empty_generates_expected_output()
{
const std::wstring projectName = L"java_empty";
ProjectSettings projectSettings;
projectSettings.setProjectFilePath(L"non_existent_project", getInputDirectoryPath(projectName));
std::shared_ptr<SourceGroupSettingsJavaEmpty> sourceGroupSettings =
std::make_shared<SourceGroupSettingsJavaEmpty>("fake_id", &projectSettings);
sourceGroupSettings->setSourceExtensions({ L".java" });
sourceGroupSettings->setExcludeFilterStrings({ L"**/Foo.java" });
sourceGroupSettings->setJavaStandard({ L"10" });
sourceGroupSettings->setSourcePaths({ getInputDirectoryPath(projectName).concatenate(L"src") });
sourceGroupSettings->setUseJreSystemLibrary(true);
sourceGroupSettings->setClasspath({
getInputDirectoryPath(projectName).concatenate(L"lib/dependency.jar"), getInputDirectoryPath(projectName).concatenate(L"classpath_dir")
});
std::shared_ptr<ApplicationSettings> applicationSettings = ApplicationSettings::getInstance();
std::vector<FilePath> storedJreSystemLibraryPaths = applicationSettings->getJreSystemLibraryPaths();
applicationSettings->setJreSystemLibraryPaths({ FilePath(L"test/jre/system/library/path.jar") });
generateAndCompareExpectedOutput(projectName, std::make_shared<SourceGroupJavaEmpty>(sourceGroupSettings));
applicationSettings->setJreSystemLibraryPaths(storedJreSystemLibraryPaths);
}
void test_sourcegroup_java_gradle_generates_expected_output()
{
const std::wstring projectName = L"java_gradle";
ProjectSettings projectSettings;
projectSettings.setProjectFilePath(L"non_existent_project", getInputDirectoryPath(projectName));
std::shared_ptr<SourceGroupSettingsJavaGradle> sourceGroupSettings =
std::make_shared<SourceGroupSettingsJavaGradle>("fake_id", &projectSettings);
sourceGroupSettings->setSourceExtensions({ L".java" });
sourceGroupSettings->setExcludeFilterStrings({ L"**/HelloWorld.java" });
sourceGroupSettings->setJavaStandard({ L"10" });
sourceGroupSettings->setGradleProjectFilePath({ getInputDirectoryPath(projectName).concatenate(L"build.gradle") });
sourceGroupSettings->setShouldIndexGradleTests(true);
sourceGroupSettings->setGradleDependenciesDirectory(getInputDirectoryPath(projectName).concatenate(L"gradle_dependencies"));
std::shared_ptr<ApplicationSettings> applicationSettings = ApplicationSettings::getInstance();
const FilePath storedAppPath = AppPath::getAppPath();
AppPath::setAppPath(storedAppPath.getConcatenated(L"../app").makeAbsolute());
std::vector<FilePath> storedJreSystemLibraryPaths = applicationSettings->getJreSystemLibraryPaths();
applicationSettings->setJreSystemLibraryPaths({ FilePath(L"test/jre/system/library/path.jar") });
generateAndCompareExpectedOutput(projectName, std::make_shared<SourceGroupJavaGradle>(sourceGroupSettings));
applicationSettings->setJreSystemLibraryPaths(storedJreSystemLibraryPaths);
AppPath::setAppPath(storedAppPath);
}
void test_sourcegroup_java_maven_generates_expected_output()
{
std::vector<FilePath> mavenPaths = utility::getMavenExecutablePathDetector()->getPaths();
TS_ASSERT(!mavenPaths.empty());
if (!mavenPaths.empty())
{
ApplicationSettings::getInstance()->setMavenPath(mavenPaths.front());
}
const std::wstring projectName = L"java_maven";
ProjectSettings projectSettings;
projectSettings.setProjectFilePath(L"non_existent_project", getInputDirectoryPath(projectName));
std::shared_ptr<SourceGroupSettingsJavaMaven> sourceGroupSettings =
std::make_shared<SourceGroupSettingsJavaMaven>("fake_id", &projectSettings);
sourceGroupSettings->setSourceExtensions({ L".java" });
sourceGroupSettings->setExcludeFilterStrings({ L"**/Foo.java" });
sourceGroupSettings->setJavaStandard({ L"10" });
sourceGroupSettings->setMavenProjectFilePath({ getInputDirectoryPath(projectName).concatenate(L"my-app/pom.xml") });
sourceGroupSettings->setShouldIndexMavenTests(true);
sourceGroupSettings->setMavenDependenciesDirectory(getInputDirectoryPath(projectName).concatenate(L"maven_dependencies"));
std::shared_ptr<ApplicationSettings> applicationSettings = ApplicationSettings::getInstance();
std::vector<FilePath> storedJreSystemLibraryPaths = applicationSettings->getJreSystemLibraryPaths();
applicationSettings->setJreSystemLibraryPaths({ FilePath(L"test/jre/system/library/path.jar") });
generateAndCompareExpectedOutput(projectName, std::make_shared<SourceGroupJavaMaven>(sourceGroupSettings));
applicationSettings->setJreSystemLibraryPaths(storedJreSystemLibraryPaths);
}
void test_sourcegroup_java_sonargraph_with_java_modules_generates_expected_output()
{
const std::wstring projectName = L"java_sonargraph";
ProjectSettings projectSettings;
projectSettings.setProjectFilePath(L"non_existent_project", getInputDirectoryPath(projectName));
std::shared_ptr<SourceGroupSettingsJavaSonargraph> sourceGroupSettings =
std::make_shared<SourceGroupSettingsJavaSonargraph>("fake_id", &projectSettings);
sourceGroupSettings->setUseJreSystemLibrary(true);
sourceGroupSettings->setClasspath({
FilePath(L"test/classpath/file.jar"), FilePath(L"test/classpath/dir")
});
sourceGroupSettings->setSonargraphProjectPath(getInputDirectoryPath(projectName).concatenate(L"sonargraph/system.sonargraph"));
std::shared_ptr<ApplicationSettings> applicationSettings = ApplicationSettings::getInstance();
std::vector<FilePath> storedJreSystemLibraryPaths = applicationSettings->getJreSystemLibraryPaths();
applicationSettings->setJreSystemLibraryPaths({ FilePath(L"test/jre/system/library/path.jar") });
generateAndCompareExpectedOutput(projectName, std::make_shared<SourceGroupJavaSonargraph>(sourceGroupSettings));
applicationSettings->setJreSystemLibraryPaths(storedJreSystemLibraryPaths);
}
// Special Tests
void test_sourcegroup_java_sonargraph_with_cpp_modules_does_not_generate_output()
{
const std::wstring projectName = L"cxx_sonargraph_cpp_manual";
const FilePath sonargraphProjectFilePath(getInputDirectoryPath(projectName).concatenate(L"sonargraph/system.sonargraph"));
TS_ASSERT(sonargraphProjectFilePath.exists());
ProjectSettings projectSettings;
projectSettings.setProjectFilePath(L"non_existent_project", getInputDirectoryPath(projectName));
std::shared_ptr<SourceGroupSettingsJavaSonargraph> sourceGroupSettings = std::make_shared<SourceGroupSettingsJavaSonargraph>("fake_id", &projectSettings);
sourceGroupSettings->setSonargraphProjectPath(sonargraphProjectFilePath);
std::shared_ptr<TextAccess> output = generateExpectedOutput(projectName, std::make_shared<SourceGroupJavaSonargraph>(sourceGroupSettings));
TS_ASSERT_EQUALS(0, output->getLineCount());
}
void test_sourcegroup_cxx_sonargraph_with_java_modules_does_not_generate_output()
{
const std::wstring projectName = L"java_sonargraph";
const FilePath sonargraphProjectFilePath(getInputDirectoryPath(projectName).concatenate(L"sonargraph/system.sonargraph"));
TS_ASSERT(sonargraphProjectFilePath.exists());
ProjectSettings projectSettings;
projectSettings.setProjectFilePath(L"non_existent_project", getInputDirectoryPath(projectName));
std::shared_ptr<SourceGroupSettingsCxxSonargraph> sourceGroupSettings = std::make_shared<SourceGroupSettingsCxxSonargraph>("fake_id", &projectSettings);
sourceGroupSettings->setSonargraphProjectPath(sonargraphProjectFilePath);
std::shared_ptr<TextAccess> output = generateExpectedOutput(projectName, std::make_shared<SourceGroupCxxSonargraph>(sourceGroupSettings));
TS_ASSERT_EQUALS(0, output->getLineCount());
}
void test_can_destroy_application_instance()
{
Application::destroyInstance();
TS_ASSERT_EQUALS(0, Application::getInstance().use_count());
}
// Utility
private:
static FilePath getInputDirectoryPath(const std::wstring& projectName)
{
return FilePath(L"data/SourceGroupTestSuite/" + projectName + L"/input").makeAbsolute();
}
static FilePath getOutputDirectoryPath(const std::wstring& projectName)
{
return FilePath(L"data/SourceGroupTestSuite/" + projectName + L"/expected_output").makeAbsolute();
}
std::string setupJavaEnvironmentFactory()
{
if (!JavaEnvironmentFactory::getInstance())
{
std::string errorString;
#ifdef _WIN32
const std::string separator = ";";
#else
const std::string separator = ":";
#endif
std::string classPath = "";
{
const std::vector<std::wstring> jarNames = utility::getRequiredJarNames();
for (size_t i = 0; i < jarNames.size(); i++)
{
if (i != 0)
{
classPath += separator;
}
classPath += FilePath(L"../app/data/java/lib/").concatenate(jarNames[i]).str();
}
}
JavaEnvironmentFactory::createInstance(
classPath,
errorString
);
return errorString;
}
return "";
}
void generateAndCompareExpectedOutput(
std::wstring projectName,
std::shared_ptr<const SourceGroup> sourceGroup)
{
const std::shared_ptr<const TextAccess> output = generateExpectedOutput(projectName, sourceGroup);
const FilePath expectedOutputFilePath = getOutputDirectoryPath(projectName).concatenate(L"output.txt");
if (s_updateExpectedOutput || !expectedOutputFilePath.exists())
{
std::ofstream expectedOutputFile;
expectedOutputFile.open(expectedOutputFilePath.str());
expectedOutputFile << output->getText();
expectedOutputFile.close();
}
else
{
const std::shared_ptr<const TextAccess> expectedOutput = TextAccess::createFromFile(expectedOutputFilePath);
TSM_ASSERT_EQUALS(L"Output does not match the expected line count for project \"" + projectName + L"\".", expectedOutput->getLineCount(), output->getLineCount());
if (expectedOutput->getLineCount() == output->getLineCount())
{
for (size_t i = 1; i <= expectedOutput->getLineCount(); i++)
{
TS_ASSERT_EQUALS(expectedOutput->getLine(i), output->getLine(i));
}
}
}
}
std::shared_ptr<TextAccess> generateExpectedOutput(
std::wstring projectName,
std::shared_ptr<const SourceGroup> sourceGroup)
{
const FilePath projectDataRoot = getInputDirectoryPath(projectName).makeAbsolute();
std::vector<std::shared_ptr<IndexerCommand>> indexerCommands = sourceGroup->getIndexerCommands(sourceGroup->getAllSourceFilePaths());
std::sort(
indexerCommands.begin(),
indexerCommands.end(),
[](std::shared_ptr<IndexerCommand> a, std::shared_ptr<IndexerCommand> b)
{
return a->getSourceFilePath().wstr() < b->getSourceFilePath().wstr();
}
);
std::wstring outputString;
for (std::shared_ptr<IndexerCommand> indexerCommand : indexerCommands)
{
outputString += indexerCommandToString(indexerCommand, projectDataRoot);
}
return TextAccess::createFromString(utility::encodeToUtf8(outputString));
}
std::wstring indexerCommandToString(std::shared_ptr<IndexerCommand> indexerCommand, const FilePath& baseDirectory)
{
if (indexerCommand)
{
if (std::shared_ptr<const IndexerCommandCxx> indexerCommandCxx = std::dynamic_pointer_cast<const IndexerCommandCxx>(indexerCommand))
{
return indexerCommandCxxToString(indexerCommandCxx, baseDirectory);
}
if (std::shared_ptr<const IndexerCommandJava> indexerCommandJava = std::dynamic_pointer_cast<const IndexerCommandJava>(indexerCommand))
{
return indexerCommandJavaToString(indexerCommandJava, baseDirectory);
}
return L"Unsupported indexer command type: " + utility::decodeFromUtf8(indexerCommandTypeToString(indexerCommand->getIndexerCommandType()));
}
return L"No IndexerCommand provided.";
}
std::wstring indexerCommandCxxToString(std::shared_ptr<const IndexerCommandCxx> indexerCommand, const FilePath& baseDirectory)
{
std::wstring result;
result += L"SourceFilePath: \"" + indexerCommand->getSourceFilePath().getRelativeTo(baseDirectory).wstr() + L"\"\n";
for (const FilePath& indexedPath : indexerCommand->getIndexedPaths())
{
result += L"\tIndexedPath: \"" + indexedPath.getRelativeTo(baseDirectory).wstr() + L"\"\n";
}
for (std::wstring compilerFlag : indexerCommand->getCompilerFlags())
{
FilePath flagAsPath(compilerFlag);
if (flagAsPath.exists())
{
compilerFlag = flagAsPath.getRelativeTo(baseDirectory).wstr();
}
result += L"\tCompilerFlag: \"" + compilerFlag + L"\"\n";
}
for (const FilePathFilter& filter : indexerCommand->getExcludeFilters())
{
result += L"\tExcludeFilter: \"" + filter.wstr() + L"\"\n";
}
return result;
}
std::wstring indexerCommandJavaToString(std::shared_ptr<const IndexerCommandJava> indexerCommand, const FilePath& baseDirectory)
{
std::wstring result;
result += L"SourceFilePath: \"" + indexerCommand->getSourceFilePath().getRelativeTo(baseDirectory).wstr() + L"\"\n";
result += L"\tLanguageStandard: \"" + indexerCommand->getLanguageStandard() + L"\"\n";
for (const FilePath& classPathItem : indexerCommand->getClassPath())
{
result += L"\tClassPathItem: \"" + classPathItem.getRelativeTo(baseDirectory).wstr() + L"\"\n";
}
return result;
}
};