logic: added support for sonargraph manual cpp modules

This commit is contained in:
mlangkabel
2018-06-11 18:54:55 +02:00
parent 1c9b4c1afd
commit b1317457ab
21 changed files with 437 additions and 1 deletions
@@ -0,0 +1,63 @@
SourceFilePath: "src/tictactoe/src/artificial_player.cpp"
LanguageStandard: "c++17"
IndexedPath: "src/tictactoe/src/artificial_player.cpp"
IndexedPath: "test/indexed/header/path"
CompilerFlag: "-isystem"
CompilerFlag: "src/tictactoe/include"
CompilerFlag: "-v"
HeaderSearchPath: "test/header/search/path"
FrameworkSearchPath: "test/framework/search/path"
SourceFilePath: "src/tictactoe/src/field.cpp"
LanguageStandard: "c++17"
IndexedPath: "src/tictactoe/src/field.cpp"
IndexedPath: "test/indexed/header/path"
CompilerFlag: "-isystem"
CompilerFlag: "src/tictactoe/include"
CompilerFlag: "-v"
HeaderSearchPath: "test/header/search/path"
FrameworkSearchPath: "test/framework/search/path"
SourceFilePath: "src/tictactoe/src/human_player.cc"
LanguageStandard: "c++17"
IndexedPath: "src/tictactoe/src/human_player.cc"
IndexedPath: "test/indexed/header/path"
CompilerFlag: "-isystem"
CompilerFlag: "src/tictactoe/include"
CompilerFlag: "-v"
HeaderSearchPath: "test/header/search/path"
FrameworkSearchPath: "test/framework/search/path"
SourceFilePath: "src/tictactoe/src/io.cpp"
LanguageStandard: "c++17"
IndexedPath: "src/tictactoe/src/io.cpp"
IndexedPath: "test/indexed/header/path"
CompilerFlag: "-isystem"
CompilerFlag: "src/tictactoe/include"
CompilerFlag: "-v"
HeaderSearchPath: "test/header/search/path"
FrameworkSearchPath: "test/framework/search/path"
SourceFilePath: "src/tictactoe/src/main.cpp"
LanguageStandard: "c++17"
IndexedPath: "src/tictactoe/src/main.cpp"
IndexedPath: "test/indexed/header/path"
CompilerFlag: "-isystem"
CompilerFlag: "src/tictactoe/include"
CompilerFlag: "-v"
HeaderSearchPath: "test/header/search/path"
FrameworkSearchPath: "test/framework/search/path"
SourceFilePath: "src/tictactoe/src/player.cpp"
LanguageStandard: "c++17"
IndexedPath: "src/tictactoe/src/player.cpp"
IndexedPath: "test/indexed/header/path"
CompilerFlag: "-isystem"
CompilerFlag: "src/tictactoe/include"
CompilerFlag: "-v"
HeaderSearchPath: "test/header/search/path"
FrameworkSearchPath: "test/framework/search/path"
SourceFilePath: "src/tictactoe/src/tictactoe.cpp"
LanguageStandard: "c++17"
IndexedPath: "src/tictactoe/src/tictactoe.cpp"
IndexedPath: "test/indexed/header/path"
CompilerFlag: "-isystem"
CompilerFlag: "src/tictactoe/include"
CompilerFlag: "-v"
HeaderSearchPath: "test/header/search/path"
FrameworkSearchPath: "test/framework/search/path"
@@ -0,0 +1,12 @@
<?xml version="1.0" ?>
<ns2:softwareSystem xmlns:ns2="http://www.hello2morrow.com/sonargraph/core" id="648f7faac44bfd5ac3cdd4bb5222efee" version="9.7.0.500">
<description></description>
<module xmlns:ns4="http://www.hello2morrow.com/sonargraph/languageprovider/cplusplus" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="ns4:xsdCppManualModule" name="TicTacToe" id="7f4e2c6be18676bc5959cfb7c802d27e" language="CPlusPlus">
<description></description>
<rootPath name="./tictactoe/src"></rootPath>
<basePathForIncludes>../src/tictactoe</basePathForIncludes>
<sourceFileExtensions>.cpp,.cc</sourceFileExtensions>
<moduleCompilerOptions installationCompilerDefinitionRef="CopyOfVisualCpp_14.0_x86">-I./include
-v</moduleCompilerOptions>
</module>
</ns2:softwareSystem>
+2
View File
@@ -542,6 +542,8 @@ add_files(
utility/sonargraph/SonargraphXsdAbstractSystemExtension.h
utility/sonargraph/SonargraphXsdCmakeJsonModule.cpp
utility/sonargraph/SonargraphXsdCmakeJsonModule.h
utility/sonargraph/SonargraphXsdCppManualModule.cpp
utility/sonargraph/SonargraphXsdCppManualModule.h
utility/sonargraph/SonargraphXsdCppSystemSettings.cpp
utility/sonargraph/SonargraphXsdCppSystemSettings.h
utility/sonargraph/SonargraphXsdJavaModule.cpp
@@ -4,6 +4,7 @@
#include "utility/logging/logging.h"
#include "utility/sonargraph/SonargraphXsdCmakeJsonModule.h"
#include "utility/sonargraph/SonargraphXsdCppManualModule.h"
#include "utility/sonargraph/SonargraphXsdJavaModule.h"
#include "utility/sonargraph/SonargraphXsdRootPath.h"
#include "utility/sonargraph/SonargraphSoftwareSystem.h"
@@ -24,6 +25,10 @@ namespace Sonargraph
{
return module;
}
if (std::shared_ptr<XsdCppManualModule> module = XsdCppManualModule::create(element, parent))
{
return module;
}
if (std::shared_ptr<XsdJavaModule> module = XsdJavaModule::create(element, parent))
{
return module;
@@ -0,0 +1,299 @@
#include "utility/sonargraph/SonargraphXsdCppManualModule.h"
#include "tinyxml/tinyxml.h"
#include "data/indexer/IndexerCommandCxxEmpty.h"
#include "settings/ApplicationSettings.h"
#include "settings/SourceGroupSettingsCxxSonargraph.h"
#include "utility/file/FileSystem.h"
#include "utility/sonargraph/SonargraphSoftwareSystem.h"
#include "utility/sonargraph/utilitySonargraph.h"
#include "utility/utility.h"
#include "utility/utilityFile.h"
#include "utility/utilityXml.h"
namespace Sonargraph
{
std::string XsdCppManualModule::getXsdTypeName()
{
return "xsdCppManualModule";
}
std::vector<std::wstring> XsdCppManualModule::getIncludeOptionPrefixes()
{
// make sure that none of these prefixes is the prefix of a prefix that appears further down in the list
return {
L"-I",
L"--include_directory=",
L"--sys_include="
};
}
std::shared_ptr<XsdCppManualModule> XsdCppManualModule::create(const TiXmlElement* element, std::weak_ptr<SoftwareSystem> parent)
{
if (!utility::xmlElementHasAttribute(element, "xsi:type") || utility::sonargraphXmlElementIsType(element, getXsdTypeName()))
{
std::shared_ptr<XsdCppManualModule> module = std::shared_ptr<XsdCppManualModule>(new XsdCppManualModule());
if (module->init(element, parent))
{
return module;
}
}
return std::shared_ptr<XsdCppManualModule>();
}
LanguageType XsdCppManualModule::getSupportedLanguage() const
{
return LANGUAGE_CPP;
}
std::set<FilePath> XsdCppManualModule::getAllSourcePaths() const
{
FilePath baseDirectory;
if (std::shared_ptr<const SoftwareSystem> softwareSystem = getSoftwareSystem())
{
baseDirectory = softwareSystem->getBaseDirectory();
}
std::set<FilePath> sourcePaths;
for (std::shared_ptr<XsdRootPath> rootPath : getRootPaths())
{
sourcePaths.insert(rootPath->getFilePath(baseDirectory));
}
return sourcePaths;
}
std::set<FilePath> XsdCppManualModule::getAllSourceFilePathsCanonical() const
{
const std::vector<FilePathFilter> excludeFilters = getDerivedExcludeFilters();
const std::vector<FilePathFilter> includeFilters = getDerivedIncludeFilters();
std::set<FilePath> sourceFilePaths;
for (const FileInfo& fileInfo : FileSystem::getFileInfosFromPaths(utility::getTopLevelPaths(getAllSourcePaths()), m_sourceFileExtensions))
{
const FilePath sourceFilePath = fileInfo.path.getCanonical();
bool excludeMatches = false;
for (const FilePathFilter& excludeFilter : excludeFilters)
{
if (excludeFilter.isMatching(sourceFilePath))
{
excludeMatches = true;
break;
}
}
if (excludeMatches)
{
for (const FilePathFilter& includeFilter : includeFilters)
{
if (includeFilter.isMatching(sourceFilePath))
{
excludeMatches = false;
break;
}
}
}
if (!excludeMatches)
{
sourceFilePaths.insert(sourceFilePath);
}
}
return sourceFilePaths;
}
std::set<FilePath> XsdCppManualModule::getAllCxxHeaderSearchPathsCanonical() const
{
std::shared_ptr<const SoftwareSystem> softwareSystem = getSoftwareSystem();
if (!softwareSystem)
{
return std::set<FilePath>();
}
const std::vector<std::wstring> optionPrefixes = getIncludeOptionPrefixes();
const FilePath baseDir = softwareSystem->getBaseDirectory();
const FilePath baseIncludeDir = m_basePathForIncludes.isAbsolute() ? m_basePathForIncludes : baseDir.getConcatenated(m_basePathForIncludes);
std::set<FilePath> headerSearchPaths;
for (const std::wstring& compilerOption : m_moduleCompilerOptions)
{
for (const std::wstring& optionPrefix : optionPrefixes)
{
if (utility::isPrefix(optionPrefix, compilerOption))
{
FilePath headerSearchPath(utility::trim(compilerOption.substr(optionPrefix.size())));
if (headerSearchPath.isAbsolute())
{
headerSearchPaths.insert(headerSearchPath);
}
else
{
headerSearchPaths.insert(baseIncludeDir.getConcatenated(headerSearchPath));
}
break;
}
}
}
return headerSearchPaths;
}
std::vector<std::shared_ptr<IndexerCommand>> XsdCppManualModule::getIndexerCommands(
std::shared_ptr<const SourceGroupSettings> sourceGroupSettings,
std::shared_ptr<const ApplicationSettings> appSettings) const
{
std::shared_ptr<const SoftwareSystem> softwareSystem = getSoftwareSystem();
if (!softwareSystem)
{
return std::vector<std::shared_ptr<IndexerCommand>>();
}
std::vector<std::shared_ptr<IndexerCommand>> indexerCommands;
std::set<FilePath> indexedHeaderPaths;
std::string languageStandard = SourceGroupSettingsWithCppStandard::getDefaultCppStandardStatic();
if (std::shared_ptr<const SourceGroupSettingsCxxSonargraph> sonargraphSettings =
std::dynamic_pointer_cast<const SourceGroupSettingsCxxSonargraph>(sourceGroupSettings))
{
indexedHeaderPaths = utility::toSet(sonargraphSettings->getIndexedHeaderPathsExpandedAndAbsolute());
languageStandard = sonargraphSettings->getCppStandard();
}
else
{
LOG_ERROR("Source group doesn't specify language standard. Falling back to \"" + languageStandard + "\".");
LOG_ERROR("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;
{
const std::vector<std::wstring> optionPrefixes = getIncludeOptionPrefixes();
const FilePath baseIncludeDir = m_basePathForIncludes.isAbsolute() ? m_basePathForIncludes : softwareSystem->getBaseDirectory().getConcatenated(m_basePathForIncludes);
for (const std::wstring& compilerOption : m_moduleCompilerOptions)
{
bool isIncludeOption = false;
for (const std::wstring& optionPrefix : optionPrefixes)
{
if (utility::isPrefix(optionPrefix, compilerOption))
{
isIncludeOption = true;
processedOptions.push_back(L"-isystem");
FilePath headerSearchPath(utility::trim(compilerOption.substr(optionPrefix.size())));
if (headerSearchPath.isAbsolute())
{
processedOptions.push_back(headerSearchPath.wstr());
}
else
{
processedOptions.push_back(baseIncludeDir.getConcatenated(headerSearchPath).wstr());
}
break;
}
}
if (!isIncludeOption)
{
processedOptions.push_back(compilerOption);
}
}
}
for (const FilePath& sourceFilePath : getAllSourceFilePathsCanonical())
{
indexerCommands.push_back(std::make_shared<IndexerCommandCxxEmpty>(
sourceFilePath,
utility::concat(indexedHeaderPaths, { sourceFilePath }),
excludeFilters,
includeFilters,
softwareSystem->getBaseDirectory(),
systemHeaderSearchPaths,
frameworkSearchPaths,
processedOptions,
languageStandard
));
}
return indexerCommands;
}
XsdCppManualModule::XsdCppManualModule()
: m_basePathForIncludes(L".")
, m_sourceFileExtensions({L".cpp"})
{
}
bool XsdCppManualModule::init(const TiXmlElement* element, std::weak_ptr<SoftwareSystem> parent)
{
if (!XsdAbstractModule::init(element, parent))
{
return false;
}
if (element != nullptr)
{
{
const TiXmlElement* basePathForIncludesElement = element->FirstChildElement("basePathForIncludes");
if (basePathForIncludesElement != nullptr)
{
const char* text = basePathForIncludesElement->GetText();
if (text != nullptr)
{
m_basePathForIncludes = FilePath(utility::decodeFromUtf8(text));
}
else
{
LOG_ERROR("Unable to parse \"basePathForIncludes\" element of Sonargraph " + getXsdTypeName() + ".");
return false;
}
}
}
{
const TiXmlElement* sourceFileExtensionsElement = element->FirstChildElement("sourceFileExtensions");
if (sourceFileExtensionsElement != nullptr)
{
const char* text = sourceFileExtensionsElement->GetText();
if (text != nullptr)
{
m_sourceFileExtensions.clear();
for (const std::wstring extension : utility::split<std::vector<std::wstring>>(utility::decodeFromUtf8(text), L","))
{
m_sourceFileExtensions.push_back(utility::trim(extension));
}
}
else
{
LOG_ERROR("Unable to parse \"sourceFileExtensions\" element of Sonargraph " + getXsdTypeName() + ".");
return false;
}
}
}
for (const TiXmlElement* moduleCompilerOptionsElement : utility::getXmlChildElementsWithName(element, "moduleCompilerOptions"))
{
const char* text = moduleCompilerOptionsElement->GetText();
if (text != nullptr)
{
for (const std::wstring& s : utility::splitToVector(utility::decodeFromUtf8(text), L' '))
{
m_moduleCompilerOptions.push_back(utility::trim(s));
}
}
}
return true;
}
return false;
}
}
@@ -0,0 +1,35 @@
#ifndef SONARGRAPH_XSD_CPP_MANUAL_MODULE_H
#define SONARGRAPH_XSD_CPP_MANUAL_MODULE_H
#include "utility/sonargraph/SonargraphXsdAbstractModule.h"
#include "utility/sonargraph/SonargraphXsdRootPathWithFiles.h"
namespace Sonargraph
{
class XsdCppManualModule : public XsdAbstractModule
{
public:
static std::string getXsdTypeName();
static std::vector<std::wstring> getIncludeOptionPrefixes();
static std::shared_ptr<XsdCppManualModule> create(const TiXmlElement* element, std::weak_ptr<SoftwareSystem> parent);
LanguageType getSupportedLanguage() const override;
std::set<FilePath> getAllSourcePaths() const override;
std::set<FilePath> getAllSourceFilePathsCanonical() const override;
std::set<FilePath> getAllCxxHeaderSearchPathsCanonical() const override;
std::vector<std::shared_ptr<IndexerCommand>> getIndexerCommands(
std::shared_ptr<const SourceGroupSettings> sourceGroupSettings,
std::shared_ptr<const ApplicationSettings> appSettings) const override;
protected:
XsdCppManualModule();
bool init(const TiXmlElement* element, std::weak_ptr<SoftwareSystem> parent);
FilePath m_basePathForIncludes;
std::vector<std::wstring> m_sourceFileExtensions;
std::vector<std::wstring> m_moduleCompilerOptions;
};
}
#endif // SONARGRAPH_XSD_CPP_MANUAL_MODULE_H
+21 -1
View File
@@ -33,6 +33,21 @@ public:
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";
@@ -157,8 +172,13 @@ public:
{
result += L"\tIndexedPath: \"" + indexedPath.getRelativeTo(baseDirectory).wstr() + L"\"\n";
}
for (const std::wstring& compilerFlag : indexerCommand->getCompilerFlags())
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())