logic: added support for sonargraph manual cpp modules
This commit is contained in:
+63
@@ -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"
|
||||
+12
@@ -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>
|
||||
@@ -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
|
||||
@@ -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())
|
||||
|
||||
Reference in New Issue
Block a user