data: Added HeaderSearchPaths to Application- and ProjectSettings
This change allows for parsing of a real codebase by specifying the system header search paths in ApplicationSettings.xml and the additional header search paths in ProjectSettings.xml. Both settings files are now documented in ApplicationSettings_template.xml and ProjectSettings_template.xml, which show all possible settings for each file. This change also fixes some parsing edge cases that occured.
This commit is contained in:
@@ -8,5 +8,7 @@
|
||||
/bin/test/data/log/
|
||||
|
||||
/bin/app/data/window_settings.ini
|
||||
/bin/app/data/ApplicationSettings.xml
|
||||
/bin/app/data/ProjectSettings.xml
|
||||
|
||||
.DS_Store
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<config>
|
||||
<code>
|
||||
<TabWidth>4</TabWidth>
|
||||
<FontName>Courier</FontName>
|
||||
<FontSize>12</FontSize>
|
||||
<LinkColor>235 235 235 255</LinkColor>
|
||||
<ScopeColor>215 230 240 100</ScopeColor>
|
||||
<ActiveLinkColor>210 240 70 100</ActiveLinkColor>
|
||||
</code>
|
||||
</config>
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- INTEGER: int e.g 123 -->
|
||||
<!-- DECIMAL: float e.g 123.456 -->
|
||||
<!-- STRING: string e.g hello -->
|
||||
<!-- COLOR: int int int int - rgba e.g. 125 125 125 255 -->
|
||||
|
||||
<config>
|
||||
<source>
|
||||
<HeaderSearchPaths><!-- STRING: system header search paths separated by | --></HeaderSearchPaths>
|
||||
</source>
|
||||
|
||||
<code>
|
||||
<TabWidth><!-- INTEGER: number of spaces to represent a tab in code files --></TabWidth>
|
||||
|
||||
<FontName><!-- STRING: name of the font used for source view --></FontName> <!-- DEPRECATED -->
|
||||
<FontSize><!-- INTEGER: size of the font in the source view --></FontSize> <!-- DEPRECATED -->
|
||||
|
||||
<LinkColor><!-- COLOR: color of clickable elements in the source view --></LinkColor>
|
||||
<ScopeColor><!-- COLOR: color of clickable scopes in the source view --></ScopeColor>
|
||||
<ActiveLinkColor><!-- COLOR: color of active elements or scopes in the source view --></ActiveLinkColor>
|
||||
</code>
|
||||
</config>
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<config>
|
||||
<SourcePath>data/src</SourcePath>
|
||||
</config>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- INTEGER: int e.g 123 -->
|
||||
<!-- DECIMAL: float e.g 123.456 -->
|
||||
<!-- STRING: string e.g hello -->
|
||||
<!-- COLOR: int int int int - rgba e.g. 125 125 125 255 -->
|
||||
|
||||
<config>
|
||||
<source>
|
||||
<SourcePath><!-- STRING: root folder for source code parsing, also used as header search path --></SourcePath>
|
||||
<HeaderSearchPaths><!-- STRING: header search paths separated by | --></HeaderSearchPaths>
|
||||
</source>
|
||||
</config>
|
||||
@@ -1,3 +1,9 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
const bool *abd(int abc, int bca);
|
||||
|
||||
bool const *abc(int a, int b);
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
<Float>3.1416</Float>
|
||||
<String>Hello World!</String>
|
||||
|
||||
<SourcePath>data</SourcePath>
|
||||
<source>
|
||||
<SourcePath>data</SourcePath>
|
||||
<HeaderSearchPaths>data/|src/</HeaderSearchPaths>
|
||||
</source>
|
||||
</config>
|
||||
|
||||
|
||||
@@ -1,4 +1,22 @@
|
||||
ConfigManager.cpp ERROR: value path/to/nowhere is not present in config.
|
||||
Token.cpp ERROR: Location Id was not referenced by this Token.
|
||||
Node.cpp WARNING: Cannot change NodeType after it was already set from namespace to class
|
||||
Edge.cpp ERROR: Nodes are not plain copies.
|
||||
Storage.cpp INFO: class: A <input.cc 1:7 1:7>
|
||||
Storage.cpp INFO: method: A::A <input.cc 4:2 4:2>
|
||||
Storage.cpp INFO: global usage: A::A -> A::count <input.cc 5:3 5:7>
|
||||
Storage.cpp INFO: method: A::getCount <input.cc 8:13 8:20>
|
||||
Storage.cpp INFO: global usage: A::getCount -> A::count <input.cc 10:10 10:14>
|
||||
Storage.cpp INFO: method: A::process <input.cc 14:15 14:21>
|
||||
Storage.cpp INFO: field: A::count <input.cc 17:13 17:17>
|
||||
Storage.cpp INFO: class: B <input.cc 20:7 20:7>
|
||||
Storage.cpp INFO: inheritance: B : A <input.cc 21:4 21:11>
|
||||
Storage.cpp INFO: method: B::process <input.cc 24:15 24:21>
|
||||
Storage.cpp INFO: type usage: B::process -> int <input.cc 26:3 26:5>
|
||||
Storage.cpp INFO: function: main <input.cc 30:5 30:8>
|
||||
Storage.cpp INFO: type usage: main -> B <input.cc 32:2 32:2>
|
||||
Storage.cpp INFO: call: main -> B::B <input.cc 32:4 32:4>
|
||||
Storage.cpp INFO: call: main -> A::getCount <input.cc 34:9 34:21>
|
||||
Storage.cpp INFO: class: A <input.cc 1:7 1:7>
|
||||
Storage.cpp INFO: method: A::A <input.cc 4:2 4:2>
|
||||
Storage.cpp INFO: global usage: A::A -> A::count <input.cc 5:3 5:7>
|
||||
@@ -31,24 +49,6 @@ SearchIndex.cpp INFO:
|
||||
237 A::A
|
||||
^^^^
|
||||
|
||||
Storage.cpp INFO: class: A <input.cc 1:7 1:7>
|
||||
Storage.cpp INFO: method: A::A <input.cc 4:2 4:2>
|
||||
Storage.cpp INFO: global usage: A::A -> A::count <input.cc 5:3 5:7>
|
||||
Storage.cpp INFO: method: A::getCount <input.cc 8:13 8:20>
|
||||
Storage.cpp INFO: global usage: A::getCount -> A::count <input.cc 10:10 10:14>
|
||||
Storage.cpp INFO: method: A::process <input.cc 14:15 14:21>
|
||||
Storage.cpp INFO: field: A::count <input.cc 17:13 17:17>
|
||||
Storage.cpp INFO: class: B <input.cc 20:7 20:7>
|
||||
Storage.cpp INFO: inheritance: B : A <input.cc 21:4 21:11>
|
||||
Storage.cpp INFO: method: B::process <input.cc 24:15 24:21>
|
||||
Storage.cpp INFO: type usage: B::process -> int <input.cc 26:3 26:5>
|
||||
Storage.cpp INFO: function: main <input.cc 30:5 30:8>
|
||||
Storage.cpp INFO: type usage: main -> B <input.cc 32:2 32:2>
|
||||
Storage.cpp INFO: call: main -> B::B <input.cc 32:4 32:4>
|
||||
Storage.cpp INFO: call: main -> A::getCount <input.cc 34:9 34:21>
|
||||
Token.cpp ERROR: Location Id was not referenced by this Token.
|
||||
Node.cpp WARNING: Cannot change NodeType after it was already set from namespace to class
|
||||
Edge.cpp ERROR: Nodes are not plain copies.
|
||||
Settings.cpp WARNING: File for Settings not found.
|
||||
ConfigManager.cpp ERROR: value Bool is not present in config.
|
||||
ConfigManager.cpp ERROR: value Int is not present in config.
|
||||
@@ -64,7 +64,6 @@ ConfigManager.cpp ERROR: value Int is not present in config.
|
||||
ConfigManager.cpp ERROR: value Float is not present in config.
|
||||
ConfigManager.cpp ERROR: value String is not present in config.
|
||||
ConfigManager.cpp ERROR: value NewBool is not present in config.
|
||||
Graph.cpp ERROR: Can't remove member edge, without removing the child node.
|
||||
Storage.cpp INFO: typedef: type -> int <file.cpp 1:1 1:1>
|
||||
Storage.cpp INFO: class: Class <file.cpp 1:1 1:1>
|
||||
Storage.cpp INFO: struct: Struct <file.cpp 1:1 1:1>
|
||||
@@ -104,6 +103,7 @@ Storage.cpp INFO: global usage: isTrue -> global <file.cpp 1:7 1:7>
|
||||
Storage.cpp INFO: function: isTrue <file.cpp 1:0 1:0>
|
||||
Storage.cpp INFO: struct: Struct <file.cpp 1:0 1:0>
|
||||
Storage.cpp INFO: type usage: isTrue -> Struct <file.cpp 1:0 1:0>
|
||||
Graph.cpp ERROR: Can't remove member edge, without removing the child node.
|
||||
TextAccess.cpp WARNING: Index 'firstLine' has to be lower or equal index 'lastLine', is 3 > 2
|
||||
TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8
|
||||
TextAccess.cpp WARNING: Tried to access index 10. Maximum index is 8
|
||||
|
||||
@@ -16,6 +16,11 @@ ApplicationSettings::~ApplicationSettings()
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<std::string> ApplicationSettings::getHeaderSearchPaths() const
|
||||
{
|
||||
return getValues("source/HeaderSearchPaths", "");
|
||||
}
|
||||
|
||||
int ApplicationSettings::getCodeTabWidth() const
|
||||
{
|
||||
return getValue<int>("code/TabWidth", 4);
|
||||
|
||||
@@ -12,6 +12,10 @@ public:
|
||||
static std::shared_ptr<ApplicationSettings> getInstance();
|
||||
~ApplicationSettings();
|
||||
|
||||
// source
|
||||
std::vector<std::string> getHeaderSearchPaths() const;
|
||||
|
||||
// code
|
||||
int getCodeTabWidth() const;
|
||||
void setCodeTabWidth(int codeTabWidth);
|
||||
|
||||
|
||||
+11
-5
@@ -3,12 +3,12 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "ApplicationSettings.h"
|
||||
#include "data/access/GraphAccessProxy.h"
|
||||
#include "data/access/LocationAccessProxy.h"
|
||||
#include "data/graph/Token.h"
|
||||
#include "data/parser/cxx/CxxParser.h"
|
||||
#include "utility/FileSystem.h"
|
||||
#include "utility/logging/logging.h"
|
||||
#include "utility/messaging/type/MessageFinishedParsing.h"
|
||||
|
||||
std::shared_ptr<Project> Project::create(GraphAccessProxy* graphAccessProxy, LocationAccessProxy* locationAccessProxy)
|
||||
@@ -49,7 +49,8 @@ void Project::clearStorage()
|
||||
|
||||
void Project::parseCode()
|
||||
{
|
||||
if (ProjectSettings::getInstance()->getSourcePath() != "")
|
||||
std::string sourcePath = ProjectSettings::getInstance()->getSourcePath();
|
||||
if (sourcePath.size())
|
||||
{
|
||||
std::vector<std::string> extensions;
|
||||
extensions.push_back(".cpp");
|
||||
@@ -57,16 +58,21 @@ void Project::parseCode()
|
||||
extensions.push_back(".h");
|
||||
extensions.push_back(".hpp");
|
||||
|
||||
// Add the SourcePath as HeaderSearchPath as well.
|
||||
std::vector<std::string> headerSearchPaths = ProjectSettings::getInstance()->getHeaderSearchPaths();
|
||||
headerSearchPaths.push_back(sourcePath);
|
||||
|
||||
CxxParser parser(m_storage.get());
|
||||
parser.parseFiles(
|
||||
FileSystem::getSourceFilesFromDirectory(ProjectSettings::getInstance()->getSourcePath(), extensions)
|
||||
FileSystem::getSourceFilesFromDirectory(sourcePath, extensions),
|
||||
ApplicationSettings::getInstance()->getHeaderSearchPaths(),
|
||||
headerSearchPaths
|
||||
);
|
||||
|
||||
m_storage->logGraph();
|
||||
m_storage->logLocations();
|
||||
|
||||
MessageFinishedParsing message;
|
||||
message.dispatch();
|
||||
MessageFinishedParsing().dispatch();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,10 +22,15 @@ ProjectSettings::~ProjectSettings()
|
||||
|
||||
std::string ProjectSettings::getSourcePath() const
|
||||
{
|
||||
return getValue<std::string>("SourcePath", "");
|
||||
return getValue<std::string>("source/SourcePath", "");
|
||||
}
|
||||
|
||||
bool ProjectSettings::setSourcePath(const std::string& sourcePath)
|
||||
{
|
||||
return setValue<std::string>("SourcePath", sourcePath);
|
||||
return setValue<std::string>("source/SourcePath", sourcePath);
|
||||
}
|
||||
|
||||
std::vector<std::string> ProjectSettings::getHeaderSearchPaths() const
|
||||
{
|
||||
return getValues("source/HeaderSearchPaths", "");
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define PROJECT_SETTINGS_H
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "Settings.h"
|
||||
|
||||
@@ -11,9 +12,12 @@ public:
|
||||
static std::shared_ptr<ProjectSettings> getInstance();
|
||||
~ProjectSettings();
|
||||
|
||||
// source
|
||||
std::string getSourcePath() const;
|
||||
bool setSourcePath(const std::string& sourcePath);
|
||||
|
||||
std::vector<std::string> getHeaderSearchPaths() const;
|
||||
|
||||
private:
|
||||
ProjectSettings();
|
||||
ProjectSettings(const ProjectSettings&);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "utility/FileSystem.h"
|
||||
#include "utility/logging/logging.h"
|
||||
#include "utility/text/TextAccess.h"
|
||||
#include "utility/utilityString.h"
|
||||
|
||||
Settings::Settings()
|
||||
{
|
||||
@@ -44,3 +45,16 @@ void Settings::clear()
|
||||
{
|
||||
m_config = ConfigManager::createEmpty();
|
||||
}
|
||||
|
||||
std::vector<std::string> Settings::getValues(const std::string& key, std::string defaultValue) const
|
||||
{
|
||||
std::string value = getValue<std::string>(key, defaultValue);
|
||||
|
||||
if (value.size())
|
||||
{
|
||||
std::deque<std::string> values = utility::split(value, '|');
|
||||
return std::vector<std::string>(values.begin(), values.end());
|
||||
}
|
||||
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "utility/ConfigManager.h"
|
||||
|
||||
@@ -20,6 +21,8 @@ protected:
|
||||
template<typename T>
|
||||
T getValue(const std::string& key, T defaultValue) const;
|
||||
|
||||
std::vector<std::string> getValues(const std::string& key, std::string defaultValue) const;
|
||||
|
||||
template<typename T>
|
||||
bool setValue(const std::string& key, T value);
|
||||
|
||||
|
||||
@@ -304,6 +304,12 @@ Id Storage::onTypeUsageParsed(const ParseTypeUsage& type, const ParseFunction& f
|
||||
Node* functionNode = addNodeHierarchyWithDistinctSignature(Node::NODE_UNDEFINED_FUNCTION, function);
|
||||
Edge* edge = addTypeEdge(functionNode, Edge::EDGE_TYPE_USAGE, type);
|
||||
|
||||
if (!edge)
|
||||
{
|
||||
LOG_ERROR("Could not create type usage edge.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return edge->getId();
|
||||
}
|
||||
|
||||
@@ -598,13 +604,21 @@ TokenComponentAccess::AccessType Storage::convertAccessType(ParserClient::Access
|
||||
|
||||
TokenComponentAccess* Storage::addAccess(Node* node, ParserClient::AccessType access)
|
||||
{
|
||||
if (access != ACCESS_NONE)
|
||||
if (access == ACCESS_NONE)
|
||||
{
|
||||
std::shared_ptr<TokenComponentAccess> ptr = std::make_shared<TokenComponentAccess>(convertAccessType(access));
|
||||
node->getMemberEdge()->addComponentAccess(ptr);
|
||||
return ptr.get();
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
|
||||
Edge* edge = node->getMemberEdge();
|
||||
if (!edge)
|
||||
{
|
||||
LOG_ERROR_STREAM(<< "Cannot assign access" << access << " to node " << node->getFullName() << " because it is not a child.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<TokenComponentAccess> ptr = std::make_shared<TokenComponentAccess>(convertAccessType(access));
|
||||
edge->addComponentAccess(ptr);
|
||||
return ptr.get();
|
||||
}
|
||||
|
||||
TokenComponentAbstraction::AbstractionType Storage::convertAbstractionType(ParserClient::AbstractionType abstraction) const
|
||||
|
||||
@@ -24,5 +24,12 @@ ParseLocation::ParseLocation(
|
||||
|
||||
bool ParseLocation::isValid() const
|
||||
{
|
||||
return startLineNumber > 0 && endLineNumber >= startLineNumber;
|
||||
if (startLineNumber == endLineNumber)
|
||||
{
|
||||
return startLineNumber > 0 && startColumnNumber <= endColumnNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
return startLineNumber > 0 && startLineNumber < endLineNumber;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,10 @@ public:
|
||||
Parser(ParserClient* client);
|
||||
virtual ~Parser();
|
||||
|
||||
virtual void parseFiles(const std::vector<std::string>& filePaths) = 0;
|
||||
virtual void parseFiles(
|
||||
const std::vector<std::string>& filePaths,
|
||||
const std::vector<std::string>& systemHeaderSearchPaths,
|
||||
const std::vector<std::string>& headerSearchPaths) = 0;
|
||||
virtual void parseFile(std::shared_ptr<TextAccess> textAccess) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -281,6 +281,12 @@ void ASTVisitor::VisitCallExprInDeclBody(clang::FunctionDecl* decl, clang::CallE
|
||||
|
||||
// return nullptr;
|
||||
|
||||
if (!expr->getDirectCallee())
|
||||
{
|
||||
// TODO: Save error at location.
|
||||
return;
|
||||
}
|
||||
|
||||
m_client->onCallParsed(
|
||||
getParseLocation(expr->getSourceRange()),
|
||||
getParseFunction(decl),
|
||||
@@ -290,6 +296,12 @@ void ASTVisitor::VisitCallExprInDeclBody(clang::FunctionDecl* decl, clang::CallE
|
||||
|
||||
void ASTVisitor::VisitCallExprInDeclBody(clang::VarDecl* decl, clang::CallExpr* expr)
|
||||
{
|
||||
if (!expr->getDirectCallee())
|
||||
{
|
||||
// TODO: Save error at location.
|
||||
return;
|
||||
}
|
||||
|
||||
m_client->onCallParsed(
|
||||
getParseLocation(expr->getSourceRange()),
|
||||
getParseVariable(decl),
|
||||
@@ -478,7 +490,10 @@ std::vector<ParseTypeUsage> ASTVisitor::getParameters(clang::FunctionDecl* decla
|
||||
for (unsigned i = 0; i < declaration->getNumParams(); i++)
|
||||
{
|
||||
clang::ParmVarDecl* paramDecl = declaration->getParamDecl(i);
|
||||
parameters.push_back(getParseTypeUsage(paramDecl->getTypeSourceInfo()->getTypeLoc(), paramDecl->getType()));
|
||||
if (paramDecl->getTypeSourceInfo())
|
||||
{
|
||||
parameters.push_back(getParseTypeUsage(paramDecl->getTypeSourceInfo()->getTypeLoc(), paramDecl->getType()));
|
||||
}
|
||||
}
|
||||
|
||||
return parameters;
|
||||
|
||||
@@ -13,12 +13,41 @@ CxxParser::~CxxParser()
|
||||
{
|
||||
}
|
||||
|
||||
void CxxParser::parseFiles(const std::vector<std::string>& filePaths)
|
||||
{
|
||||
// Fake commandline flags passed to the programm. Everything after '--' will be interpreted by the ClangTool.
|
||||
void CxxParser::parseFiles(
|
||||
const std::vector<std::string>& filePaths,
|
||||
const std::vector<std::string>& systemHeaderSearchPaths,
|
||||
const std::vector<std::string>& headerSearchPaths
|
||||
){
|
||||
// Commandline flags passed to the programm. Everything after '--' will be interpreted by the ClangTool.
|
||||
std::vector<std::string> args;
|
||||
args.push_back("app");
|
||||
args.push_back("--");
|
||||
|
||||
// verbose
|
||||
// args.push_back("-v");
|
||||
|
||||
// The option '-x c++' treats subsequent input files as C++.
|
||||
const char* argv[] = { "app", "--", "-x", "c++" };
|
||||
int argc = 4;
|
||||
args.push_back("-x");
|
||||
args.push_back("c++");
|
||||
|
||||
args.push_back("-std=c++11");
|
||||
|
||||
for (const std::string& path : systemHeaderSearchPaths)
|
||||
{
|
||||
args.push_back("-isystem" + path);
|
||||
}
|
||||
|
||||
for (const std::string& path : headerSearchPaths)
|
||||
{
|
||||
args.push_back("-I" + path);
|
||||
}
|
||||
|
||||
int argc = args.size();
|
||||
const char** argv = new const char*[argc];
|
||||
for (size_t i = 0; i < args.size(); i++)
|
||||
{
|
||||
argv[i] = args[i].c_str();
|
||||
}
|
||||
|
||||
std::shared_ptr<clang::tooling::FixedCompilationDatabase> compilationDatabase(
|
||||
clang::tooling::FixedCompilationDatabase::loadFromCommandLine(argc, argv)
|
||||
|
||||
@@ -9,7 +9,10 @@ public:
|
||||
CxxParser(ParserClient* client);
|
||||
~CxxParser();
|
||||
|
||||
virtual void parseFiles(const std::vector<std::string>& filePaths);
|
||||
virtual void parseFiles(
|
||||
const std::vector<std::string>& filePaths,
|
||||
const std::vector<std::string>& systemHeaderSearchPaths,
|
||||
const std::vector<std::string>& headerSearchPaths);
|
||||
virtual void parseFile(std::shared_ptr<TextAccess> textAccess);
|
||||
};
|
||||
|
||||
|
||||
@@ -981,7 +981,7 @@ public:
|
||||
std::vector<std::string> filePaths;
|
||||
filePaths.push_back("data/CxxParserTestSuite/header.h");
|
||||
filePaths.push_back("data/CxxParserTestSuite/code.cpp");
|
||||
parser.parseFiles(filePaths);
|
||||
parser.parseFiles(filePaths, std::vector<std::string>(), std::vector<std::string>());
|
||||
|
||||
TS_ASSERT_EQUALS(client.typedefs.size(), 1);
|
||||
TS_ASSERT_EQUALS(client.classes.size(), 4);
|
||||
|
||||
@@ -117,6 +117,16 @@ public:
|
||||
TS_ASSERT_EQUALS(ProjectSettings::getInstance()->getSourcePath(), "data");
|
||||
}
|
||||
|
||||
void test_load_header_search_paths_from_file()
|
||||
{
|
||||
ProjectSettings::getInstance()->load("data/SettingsTestSuite/settings.xml");
|
||||
std::vector<std::string> paths = ProjectSettings::getInstance()->getHeaderSearchPaths();
|
||||
|
||||
TS_ASSERT_EQUALS(paths.size(), 2);
|
||||
TS_ASSERT_EQUALS(paths[0], "data/");
|
||||
TS_ASSERT_EQUALS(paths[1], "src/");
|
||||
}
|
||||
|
||||
private:
|
||||
class TestSettings
|
||||
: public Settings
|
||||
|
||||
Reference in New Issue
Block a user