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:
Eberhard Graether
2014-10-07 12:11:48 +02:00
parent d720414467
commit f41e1c429d
23 changed files with 211 additions and 57 deletions
+5
View File
@@ -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);
+4
View File
@@ -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
View File
@@ -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();
}
}
+7 -2
View File
@@ -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", "");
}
+4
View File
@@ -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&);
+14
View File
@@ -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
View File
@@ -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);
+19 -5
View File
@@ -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
+8 -1
View File
@@ -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;
}
}
+4 -1
View File
@@ -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:
+16 -1
View File
@@ -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;
+34 -5
View File
@@ -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)
+4 -1
View File
@@ -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);
};
+1 -1
View File
@@ -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);
+10
View File
@@ -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