logic: solution parsing refactor

Refactored solution parser handling to make it more generic
Also includes new parser (wip)
This commit is contained in:
Manuel Dobusch
2016-03-23 17:06:40 +01:00
parent bac394381c
commit 82db193c78
26 changed files with 1236 additions and 442 deletions
+8
View File
@@ -279,6 +279,14 @@ add_files(
utility/solution/ISolutionParser.cpp
utility/solution/ISolutionParser.h
utility/solution/SolutionParserCodeBlocks.cpp
utility/solution/SolutionParserCodeBlocks.h
utility/solution/SolutionParserEclipse.cpp
utility/solution/SolutionParserEclipse.h
utility/solution/SolutionParserManager.cpp
utility/solution/SolutionParserManager.h
utility/solution/SolutionParserUtility.cpp
utility/solution/SolutionParserUtility.h
utility/solution/SolutionParserVisualStudio.cpp
utility/solution/SolutionParserVisualStudio.h
@@ -99,10 +99,11 @@ void IDECommunicationController::handleCreateProjectMessage(const NetworkProtoco
{
if (message.valid)
{
if (message.ideId == NetworkProtocolHelper::CreateProjectMessage::IDE_ID::VS)
if (message.ideId == "vs")
{
MessageProjectNew msg;
msg.setVisualStudioSolutionPath(message.solutionFileLocation);
msg.setSolutionPath(message.solutionFileLocation);
msg.ideId = message.ideId;
msg.dispatch();
}
else
@@ -3,8 +3,12 @@
#include <sstream>
#include <string>
#include <boost/algorithm/string.hpp>
#include "utility/logging/logging.h"
#include "utility/solution/SolutionParserVisualStudio.h"
std::string NetworkProtocolHelper::m_divider = ">>";
std::string NetworkProtocolHelper::m_setActiveTokenPrefix = "setActiveToken";
std::string NetworkProtocolHelper::m_moveCursorPrefix = "moveCursor";
@@ -100,14 +104,10 @@ NetworkProtocolHelper::CreateProjectMessage NetworkProtocolHelper::parseCreatePr
{
networkMessage.solutionFileLocation = fileLocation;
if (ideId == "vs")
{
networkMessage.ideId = CreateProjectMessage::IDE_ID::VS;
}
else
{
networkMessage.ideId = CreateProjectMessage::IDE_ID::UNKNOWN;
}
std::string nonConstId = ideId;
boost::algorithm::to_lower(nonConstId);
networkMessage.ideId = nonConstId;
networkMessage.valid = true;
}
@@ -28,18 +28,12 @@ public:
public:
CreateProjectMessage()
: solutionFileLocation("")
, ideId(IDE_ID::UNKNOWN)
, ideId("")
, valid(false)
{}
enum IDE_ID
{
UNKNOWN = 0,
VS
};
std::string solutionFileLocation;
IDE_ID ideId;
std::string ideId;
bool valid;
};
@@ -8,6 +8,8 @@ class MessageProjectNew
{
public:
MessageProjectNew()
: solutionPath("")
, ideId("")
{
}
@@ -16,17 +18,18 @@ public:
return "MessageProjectNew";
}
bool fromVisualStudioSolution() const
bool fromSolution() const
{
return visualStudioSolutionPath.size() > 0;
return solutionPath.size() > 0;
}
void setVisualStudioSolutionPath(const std::string& path)
void setSolutionPath(const std::string& path)
{
visualStudioSolutionPath = path;
solutionPath = path;
}
std::string visualStudioSolutionPath;
std::string solutionPath;
std::string ideId;
};
#endif // MESSAGE_PROJECT_NEW_H
@@ -5,6 +5,11 @@ std::string ISolutionParser::getSolutionPath()
return m_solutionPath;
}
std::string ISolutionParser::getToolID() const
{
return "NONE";
}
void ISolutionParser::openSolutionFile(const std::string& solutionFilePath)
{
m_solution = loadFile(solutionFilePath);
@@ -46,3 +51,23 @@ std::string ISolutionParser::loadFile(const std::string& filePath)
return file;
}
std::vector<std::string> ISolutionParser::makePathsAbsolute(const std::vector<std::string>& paths)
{
std::vector<std::string> absolutePaths;
for (unsigned int i = 0; i < paths.size(); i++)
{
std::string path = paths[i];
boost::filesystem::path boostPath(path);
if (boostPath.is_relative())
{
path = m_solutionPath + path;
}
absolutePaths.push_back(path);
}
return absolutePaths;
}
@@ -4,6 +4,8 @@
#include <fstream>
#include <vector>
#include "settings/ProjectSettings.h"
class ISolutionParser
{
public:
@@ -13,6 +15,8 @@ public:
{};
virtual ~ISolutionParser(){};
virtual std::string getToolID() const;
void openSolutionFile(const std::string& solutionFilePath);
unsigned int getSolutionCharCount() const;
@@ -23,9 +27,18 @@ public:
virtual std::vector<std::string> getProjectFiles() = 0;
virtual std::vector<std::string> getProjectItems() = 0;
virtual ProjectSettings getProjectSettings(const std::string& solutionFilePath) = 0;
virtual std::string getIdeName() const = 0;
virtual std::string getDescription() const = 0;
virtual std::string getIconPath() const = 0;
virtual std::string getFileExtension() const = 0;
protected:
std::string loadFile(const std::string& filePath);
std::vector<std::string> makePathsAbsolute(const std::vector<std::string>& paths);
std::string m_solutionName;
std::string m_solutionPath;
std::string m_solution;
@@ -0,0 +1,217 @@
#include "SolutionParserCodeBlocks.h"
#include <set>
#include "SolutionParserUtility.h"
#include "utility/logging/logging.h"
SolutionParserCodeBlocks::SolutionParserCodeBlocks()
{
}
SolutionParserCodeBlocks::~SolutionParserCodeBlocks()
{
}
std::string SolutionParserCodeBlocks::getToolID() const
{
return "cb";
}
std::string SolutionParserCodeBlocks::getSolutionName()
{
std::string result = "";
if (m_solutionName.size() > 0)
{
size_t pos = m_solutionName.find(".cbp");
if (pos != std::string::npos)
{
result = m_solutionName.substr(0, pos);
}
else
{
result = m_solution;
}
}
return result;
}
std::vector<std::string> SolutionParserCodeBlocks::getProjects()
{
std::vector<std::string> projectFiles;
projectFiles.push_back(m_solutionName);
return projectFiles;
}
std::vector<std::string> SolutionParserCodeBlocks::getProjectFiles()
{
std::vector<std::string> projectFiles;
std::vector<std::string> projectFilesNames = getProjects();
projectFiles.push_back(loadFile(m_solutionPath + m_solutionName));
return projectFiles;
}
std::vector<std::string> SolutionParserCodeBlocks::getProjectItems()
{
std::vector<std::string> projectItems;
std::vector<std::string> projectFilesNames = getProjects();
std::vector<std::string> projectFiles = getProjectFiles();
std::vector<std::string> validFileExtensions;
validFileExtensions.push_back(".c");
validFileExtensions.push_back(".cpp");
validFileExtensions.push_back(".h");
validFileExtensions.push_back(".hpp");
for (unsigned int i = 0; i < projectFiles.size(); i++)
{
TiXmlDocument doc;
doc.Parse(projectFiles[i].c_str(), 0, TIXML_ENCODING_UTF8);
std::string error = doc.ErrorDesc();
if (error.length() > 0)
{
LOG_ERROR_STREAM(<< "Failed to parse project file " << i << ": " << error);
continue;
}
std::vector<TiXmlElement*> nodes = SolutionParserUtility::getAllTagsByNameWithAttribute(doc.RootElement(), "Unit", "filename");
if (nodes.size() > 0)
{
for (unsigned int i = 0; i < nodes.size(); i++)
{
std::string text = nodes[i]->Attribute("filename");
if (SolutionParserUtility::checkValidFileExtension(text, validFileExtensions))
{
if (boost::filesystem::exists(text))
{
projectItems.push_back(text);
continue;
}
text = m_solutionPath + "/" + text;
projectItems.push_back(text);
}
}
}
}
std::set<std::string> s(projectItems.begin(), projectItems.end());
projectItems.assign(s.begin(), s.end());
projectItems = SolutionParserUtility::resolveEnvironmentVariables(projectItems);
projectItems = makePathsAbsolute(projectItems);
return projectItems;
}
std::vector<std::string> SolutionParserCodeBlocks::getIncludePaths()
{
std::vector<std::string> includePaths;
std::vector<std::string> projectFiles = getProjectFiles();
std::vector<std::string> validExtensions;
validExtensions.push_back(".c");
validExtensions.push_back(".cpp");
validExtensions.push_back(".h");
validExtensions.push_back(".hpp");
for (unsigned int i = 0; i < projectFiles.size(); i++)
{
TiXmlDocument doc;
doc.Parse(projectFiles[i].c_str(), 0, TIXML_ENCODING_UTF8);
std::string error = doc.ErrorDesc();
if (error.length() > 0)
{
LOG_ERROR_STREAM(<< "Failed to parse project file " << i << ": " << error);
continue;
}
std::vector<TiXmlElement*> nodes = SolutionParserUtility::getAllTagsByNameWithAttribute(doc.RootElement(), "Add", "directory");
if (nodes.size() > 0)
{
for (unsigned int i = 0; i < nodes.size(); i++)
{
std::string text = nodes[i]->Attribute("directory");
includePaths.push_back(text);
}
}
}
std::set<std::string> s(includePaths.begin(), includePaths.end());
includePaths.assign(s.begin(), s.end());
includePaths = SolutionParserUtility::resolveEnvironmentVariables(includePaths);
includePaths = makePathsAbsolute(includePaths);
return includePaths;
}
ProjectSettings SolutionParserCodeBlocks::getProjectSettings(const std::string& solutionFilePath)
{
openSolutionFile(solutionFilePath);
ProjectSettings settings;
settings.setProjectName(getSolutionName());
settings.setProjectFileLocation(getSolutionPath());
settings.setVisualStudioSolutionPath(solutionFilePath);
std::vector<std::string> sourceFiles = getProjectItems();
std::vector<FilePath> sourcePaths;
for (const std::string& p : sourceFiles)
{
sourcePaths.push_back(FilePath(p));
}
std::vector<std::string> includePaths = getIncludePaths();
std::vector<FilePath> headerPaths;
for (const std::string& p : includePaths)
{
headerPaths.push_back(FilePath(p));
}
settings.setSourcePaths(sourcePaths);
settings.setHeaderSearchPaths(headerPaths);
return settings;
}
std::string SolutionParserCodeBlocks::getIdeName() const
{
return "Code Blocks";
}
std::string SolutionParserCodeBlocks::getDescription() const
{
return "idunno";
}
std::string SolutionParserCodeBlocks::getIconPath() const
{
return "icon/project_vs_256_256.png";
}
std::string SolutionParserCodeBlocks::getFileExtension() const
{
return ".cbp";
}
@@ -0,0 +1,31 @@
#ifndef SOLUTION_PARSER_CODE_BLOCKS_H
#define SOLUTION_PARSER_CODE_BLOCKS_H
#include "ISolutionParser.h"
#include "tinyxml/tinyxml.h"
class SolutionParserCodeBlocks : public ISolutionParser
{
public:
SolutionParserCodeBlocks();
virtual ~SolutionParserCodeBlocks();
virtual std::string getToolID() const;
virtual std::string getSolutionName();
virtual std::vector<std::string> getProjects();
virtual std::vector<std::string> getProjectFiles();
virtual std::vector<std::string> getProjectItems();
virtual std::vector<std::string> getIncludePaths();
virtual ProjectSettings getProjectSettings(const std::string& solutionFilePath);
virtual std::string getIdeName() const;
virtual std::string getDescription() const;
virtual std::string getIconPath() const;
virtual std::string getFileExtension() const;
};
#endif // SOLUTION_PARSER_CODE_BLOCKS_H
@@ -0,0 +1,11 @@
#ifndef SOLUTION_PARSER_ECLIPSE_H
#define SOLUTION_PARSER_ECLIPSE_H
#include "ISolutionParser.h"
class SolutionParserEclipse
{
};
#endif // SOLUTION_PARSER_ECLIPSE_H
@@ -0,0 +1,119 @@
#include "SolutionParserManager.h"
#include <boost/algorithm/string.hpp>
#include "utility/logging/logging.h"
SolutionParserManager::SolutionParserManager()
: m_solutionParsers()
{
}
SolutionParserManager::~SolutionParserManager()
{
}
void SolutionParserManager::pushSolutionParser(const std::shared_ptr<ISolutionParser>& solutionParser)
{
m_solutionParsers.push_back(solutionParser);
}
bool SolutionParserManager::canParseSolution(const std::string& ideId) const
{
std::string lIdeId = ideId;
boost::algorithm::to_lower(lIdeId);
for (unsigned int i = 0; i < m_solutionParsers.size(); i++)
{
std::string parserIdeId = m_solutionParsers[i]->getToolID();
boost::algorithm::to_lower(parserIdeId);
if (lIdeId == parserIdeId)
{
return true;
}
}
return false;
}
ProjectSettings SolutionParserManager::getProjectSettings(const std::string& ideId, const std::string& solutionFilePath) const
{
std::string lIdeId = ideId;
boost::algorithm::to_lower(lIdeId);
for (unsigned int i = 0; i < m_solutionParsers.size(); i++)
{
std::string parserIdeId = m_solutionParsers[i]->getToolID();
boost::algorithm::to_lower(parserIdeId);
if (lIdeId == parserIdeId)
{
return m_solutionParsers[i]->getProjectSettings(solutionFilePath);
}
}
LOG_ERROR_STREAM(<< "Solution type is unknown");
return ProjectSettings();
}
unsigned int SolutionParserManager::getParserCount() const
{
return m_solutionParsers.size();
}
std::string SolutionParserManager::getParserName(const unsigned int idx) const
{
if (checkIndex(idx))
{
return m_solutionParsers[idx]->getIdeName();
}
LOG_WARNING_STREAM(<< "Index is out of range, was " << idx << ". Max is " << m_solutionParsers.size() - 1);
return "";
}
std::string SolutionParserManager::getParserDescription(const unsigned int idx) const
{
if (checkIndex(idx))
{
return m_solutionParsers[idx]->getDescription();
}
LOG_WARNING_STREAM(<< "Index is out of range, was " << idx << ". Max is " << m_solutionParsers.size() - 1);
return "";
}
std::string SolutionParserManager::getParserFileEnding(const unsigned int idx) const
{
if (checkIndex(idx))
{
return m_solutionParsers[idx]->getFileExtension();
}
LOG_WARNING_STREAM(<< "Index is out of range, was " << idx << ". Max is " << m_solutionParsers.size() - 1);
return "";
}
std::string SolutionParserManager::getParserIdeId(const unsigned int idx) const
{
if (checkIndex(idx))
{
return m_solutionParsers[idx]->getToolID();
}
LOG_WARNING_STREAM(<< "Index is out of range, was " << idx << ". Max is " << m_solutionParsers.size() - 1);
return "";
}
bool SolutionParserManager::checkIndex(const unsigned int idx) const
{
return (idx < m_solutionParsers.size());
}
@@ -0,0 +1,33 @@
#ifndef SOLUTION_PARSER_MANAGER_H
#define SOLUTION_PARSER_MANAGER_H
#include <vector>
#include "ISolutionParser.h"
class SolutionParserManager
{
public:
SolutionParserManager();
~SolutionParserManager();
void pushSolutionParser(const std::shared_ptr<ISolutionParser>& solutionParser);
bool canParseSolution(const std::string& ideId) const;
ProjectSettings getProjectSettings(const std::string& ideId, const std::string& solutionFilePath) const;
unsigned int getParserCount() const;
std::string getParserName(const unsigned int idx) const;
std::string getParserDescription(const unsigned int idx) const;
std::string getParserFileEnding(const unsigned int idx) const;
std::string getParserIdeId(const unsigned int idx) const;
private:
bool checkIndex(const unsigned int idx) const;
std::vector<std::shared_ptr<ISolutionParser>> m_solutionParsers;
};
#endif // SOLUTION_PARSER_MANAGER_H
@@ -0,0 +1,310 @@
#include "SolutionParserUtility.h"
#include "utility/logging/logging.h"
#include "utility/messaging/type/MessageStatus.h"
#include "boost/filesystem/path.hpp"
#include "boost/filesystem.hpp"
TiXmlElement* SolutionParserUtility::getFirstTagByName(TiXmlElement* root, const std::string& tag)
{
TiXmlElement* element = root;
while (element)
{
if (element == NULL)
{
}
std::string value = element->Value();
if (value == tag) // "ClInclude") // || value == "ClCompile")
{
if (element->Parent() != NULL)
{
return element; // ->Parent()->ToElement();
}
}
if (element->FirstChildElement() != NULL)
{
element = element->FirstChildElement();
}
else if (element->NextSiblingElement() != NULL)
{
element = element->NextSiblingElement();
}
else
{
if (element == NULL)
{
}
while (element->Parent()->ToElement() != NULL && element->Parent()->NextSiblingElement() == NULL)
{
TiXmlElement* newElement = element->Parent()->ToElement();
if (newElement == NULL)
{
}
element = newElement;
}
if (element->Parent() != NULL && element->Parent()->NextSiblingElement() != NULL)
{
element = element->Parent()->NextSiblingElement();
}
else
{
return NULL;
}
}
}
return NULL;
}
std::vector<TiXmlElement*> SolutionParserUtility::getAllTagsByName(TiXmlElement* root, const std::string& tag)
{
std::vector<TiXmlElement*> nodes;
TiXmlElement* element = root;
while (element)
{
std::string value = element->Value();
if (value == tag)
{
nodes.push_back(element);
}
if (element->FirstChildElement() != NULL)
{
element = element->FirstChildElement();
}
else if (element->NextSiblingElement() != NULL)
{
element = element->NextSiblingElement();
}
else
{
if (element == NULL)
{
}
while (element->Parent()->ToElement() != NULL && element->Parent()->NextSiblingElement() == NULL)
{
TiXmlElement* newElement = element->Parent()->ToElement();
if (newElement == NULL)
{
}
element = newElement;
}
if (element->Parent() != NULL && element->Parent()->NextSiblingElement() != NULL)
{
element = element->Parent()->NextSiblingElement();
}
else
{
break;
}
}
}
return nodes;
}
TiXmlElement* SolutionParserUtility::getFirstTagByNameWithAttribute(TiXmlElement* root, const std::string& tag, const std::string& attribute)
{
TiXmlElement* element = root;
while (element)
{
if (element == NULL)
{
}
std::string value = element->Value();
bool hasAttribute = false;
if (element->Attribute(attribute.c_str()) != NULL)
{
hasAttribute = true;
}
if (value == tag && hasAttribute) // "ClInclude") // || value == "ClCompile")
{
if (element->Parent() != NULL)
{
return element; // ->Parent()->ToElement();
}
}
if (element->FirstChildElement() != NULL)
{
element = element->FirstChildElement();
}
else if (element->NextSiblingElement() != NULL)
{
element = element->NextSiblingElement();
}
else
{
while (element->Parent()->ToElement() != NULL && element->Parent()->NextSiblingElement() == NULL)
{
TiXmlElement* newElement = element->Parent()->ToElement();
element = newElement;
}
if (element->Parent() != NULL && element->Parent()->NextSiblingElement() != NULL)
{
element = element->Parent()->NextSiblingElement();
}
else
{
return NULL;
}
}
}
return NULL;
}
std::vector<TiXmlElement*> SolutionParserUtility::getAllTagsByNameWithAttribute(TiXmlElement* root, const std::string& tag, const std::string& attribute)
{
std::vector<TiXmlElement*> nodes;
TiXmlElement* element = root;
while (element)
{
std::string value = element->Value();
bool hasAttribute = false;
if (element->Attribute(attribute.c_str()) != NULL)
{
hasAttribute = true;
}
if (value == tag && hasAttribute)
{
nodes.push_back(element);
}
if (element->FirstChildElement() != NULL)
{
element = element->FirstChildElement();
}
else if (element->NextSiblingElement() != NULL)
{
element = element->NextSiblingElement();
}
else
{
while (element->Parent()->ToElement() != NULL && element->Parent()->NextSiblingElement() == NULL)
{
TiXmlElement* newElement = element->Parent()->ToElement();
element = newElement;
}
if (element->Parent() != NULL && element->Parent()->NextSiblingElement() != NULL)
{
element = element->Parent()->NextSiblingElement();
}
else
{
break;
}
}
}
return nodes;
}
bool SolutionParserUtility::checkValidFileExtension(const std::string& file, const std::vector<std::string>& validExtensions)
{
for (unsigned int i = 0; i < validExtensions.size(); i++)
{
size_t pos = file.find(validExtensions[i]);
if (pos != std::string::npos)
{
return true;
}
}
return false;
}
std::vector<std::string> SolutionParserUtility::resolveEnvironmentVariables(const std::vector<std::string>& paths)
{
std::vector<std::string> resolvedPaths;
for (unsigned int i = 0; i < paths.size(); i++)
{
resolvedPaths.push_back(findAndResolveEnvironmentVariable(paths[i]));
}
return resolvedPaths;
}
std::string SolutionParserUtility::findAndResolveEnvironmentVariable(const std::string& path)
{
std::string resolvedPath;
size_t pos = path.find("$(");
if (pos != std::string::npos)
{
size_t endPos = path.substr(pos).find(")");
std::string envVariable = path.substr(pos + 2, (endPos - 2) - pos);
std::string envPath = getenv(envVariable.c_str());
std::string prePath = path.substr(0, pos);
std::string postPath = path.substr(endPos + 1);
resolvedPath = prePath + envPath + postPath;
}
else
{
resolvedPath = path;
}
return resolvedPath;
}
std::vector<std::string> SolutionParserUtility::makePathsCanonical(const std::vector<std::string>& paths)
{
std::vector<std::string> canonicalPaths;
int errorCount = 0;
for (unsigned int i = 0; i < paths.size(); i++)
{
try
{
boost::filesystem::path canonicalPath = boost::filesystem::canonical(boost::filesystem::path(paths[i]));
canonicalPaths.push_back(canonicalPath.string());
}
catch (std::exception& e)
{
std::string what = e.what();
LOG_WARNING_STREAM(<< e.what());
errorCount++;
}
}
if (errorCount > 0)
{
std::stringstream errorMessage;
errorMessage << "Detected " << errorCount << " invalid include file paths. Check if the include paths of your VS project exist.";
MessageStatus(errorMessage.str(), true).dispatch();
}
return canonicalPaths;
}
@@ -0,0 +1,25 @@
#ifndef SOLUTION_PARSER_UTILITY_H
#define SOLUTION_PARSER_UTILITY_H
#include <string>
#include <vector>
#include "tinyxml/tinyxml.h"
class SolutionParserUtility
{
public:
static TiXmlElement* getFirstTagByName(TiXmlElement* root, const std::string& tag);
static std::vector<TiXmlElement*> getAllTagsByName(TiXmlElement* root, const std::string& tag);
static TiXmlElement* getFirstTagByNameWithAttribute(TiXmlElement* root, const std::string& tag, const std::string& attribute);
static std::vector<TiXmlElement*> getAllTagsByNameWithAttribute(TiXmlElement* root, const std::string& tag, const std::string& attribute);
static bool checkValidFileExtension(const std::string& file, const std::vector<std::string>& validExtensions);
static std::vector<std::string> resolveEnvironmentVariables(const std::vector<std::string>& paths);
static std::string findAndResolveEnvironmentVariable(const std::string& path);
static std::vector<std::string> makePathsCanonical(const std::vector<std::string>& paths);
};
#endif // SOLUTION_PARSER_UTILITY_H
@@ -7,6 +7,8 @@
#include "boost/filesystem/path.hpp"
#include "boost/filesystem.hpp"
#include "SolutionParserUtility.h"
#include "utility/logging/logging.h"
SolutionParserVisualStudio::SolutionParserVisualStudio()
@@ -19,6 +21,11 @@ SolutionParserVisualStudio::~SolutionParserVisualStudio()
}
std::string SolutionParserVisualStudio::getToolID() const
{
return "vs";
}
std::string SolutionParserVisualStudio::getSolutionName()
{
std::string result = "";
@@ -86,7 +93,7 @@ std::vector<std::string> SolutionParserVisualStudio::getProjectItems()
{
std::vector<std::string> projectItems = findProjectItems();
projectItems = makePathsCanonical(projectItems);
projectItems = SolutionParserUtility::makePathsCanonical(projectItems);
return projectItems;
}
@@ -95,11 +102,61 @@ std::vector<std::string> SolutionParserVisualStudio::getIncludePaths()
{
std::vector<std::string> includePaths = findIncludePaths();
includePaths = makePathsCanonical(includePaths);
includePaths = SolutionParserUtility::makePathsCanonical(includePaths);
return includePaths;
}
ProjectSettings SolutionParserVisualStudio::getProjectSettings(const std::string& solutionFilePath)
{
openSolutionFile(solutionFilePath);
ProjectSettings settings;
settings.setProjectName(getSolutionName());
settings.setProjectFileLocation(getSolutionPath());
settings.setVisualStudioSolutionPath(solutionFilePath);
std::vector<std::string> sourceFiles = getProjectItems();
std::vector<FilePath> sourcePaths;
for (const std::string& p : sourceFiles)
{
sourcePaths.push_back(FilePath(p));
}
std::vector<std::string> includePaths = getIncludePaths();
std::vector<FilePath> headerPaths;
for (const std::string& p : includePaths)
{
headerPaths.push_back(FilePath(p));
}
settings.setSourcePaths(sourcePaths);
settings.setHeaderSearchPaths(headerPaths);
return settings;
}
std::string SolutionParserVisualStudio::getIdeName() const
{
return "Visual Studio";
}
std::string SolutionParserVisualStudio::getDescription() const
{
return "Create a new project from an existing Visual Studio Solution file.";
}
std::string SolutionParserVisualStudio::getIconPath() const
{
return "icon/project_vs_256_256.png";
}
std::string SolutionParserVisualStudio::getFileExtension() const
{
return ".sln";
}
std::vector<std::string> SolutionParserVisualStudio::getProjectItemsNonCanonical()
{
return findProjectItems();
@@ -156,8 +213,8 @@ std::vector<std::string> SolutionParserVisualStudio::findProjectItems()
continue;
}
TiXmlElement* root = getFirstTagByNameWithAttribute(doc.RootElement(), "ClCompile", "Include");
TiXmlElement* headerRoot = getFirstTagByNameWithAttribute(doc.RootElement(), "ClInclude", "Include");
TiXmlElement* root = SolutionParserUtility::getFirstTagByNameWithAttribute(doc.RootElement(), "ClCompile", "Include");
TiXmlElement* headerRoot = SolutionParserUtility::getFirstTagByNameWithAttribute(doc.RootElement(), "ClInclude", "Include");
if (root != NULL)
{
// std::string text(root->GetText());
@@ -218,7 +275,7 @@ std::vector<std::string> SolutionParserVisualStudio::findProjectItems()
{
std::string filePath = child->Attribute("Include");
if (boost::filesystem::exists(filePath) && checkValidFileExtension(filePath, validFileExtensions))
if (boost::filesystem::exists(filePath) && SolutionParserUtility::checkValidFileExtension(filePath, validFileExtensions))
{
projectItems.push_back(filePath);
continue;
@@ -229,7 +286,7 @@ std::vector<std::string> SolutionParserVisualStudio::findProjectItems()
filePath = relativeProjectPaths[i] + "/" + filePath;
}
if (checkValidFileExtension(filePath, validFileExtensions))
if (SolutionParserUtility::checkValidFileExtension(filePath, validFileExtensions))
{
projectItems.push_back(filePath);
}
@@ -242,7 +299,7 @@ std::vector<std::string> SolutionParserVisualStudio::findProjectItems()
{
std::string filePath = child->Attribute("Include");
if (boost::filesystem::exists(filePath) && checkValidFileExtension(filePath, validFileExtensions))
if (boost::filesystem::exists(filePath) && SolutionParserUtility::checkValidFileExtension(filePath, validFileExtensions))
{
projectItems.push_back(filePath);
continue;
@@ -253,7 +310,7 @@ std::vector<std::string> SolutionParserVisualStudio::findProjectItems()
filePath = relativeProjectPaths[i] + "/" + filePath;
}
if (checkValidFileExtension(filePath, validFileExtensions))
if (SolutionParserUtility::checkValidFileExtension(filePath, validFileExtensions))
{
projectItems.push_back(filePath);
}
@@ -264,7 +321,7 @@ std::vector<std::string> SolutionParserVisualStudio::findProjectItems()
std::set<std::string> s(projectItems.begin(), projectItems.end());
projectItems.assign(s.begin(), s.end());
projectItems = resolveEnvironmentVariables(projectItems);
projectItems = SolutionParserUtility::resolveEnvironmentVariables(projectItems);
projectItems = makePathsAbsolute(projectItems);
return projectItems;
@@ -295,7 +352,7 @@ std::vector<std::string> SolutionParserVisualStudio::findIncludePaths()
continue;
}
std::vector<TiXmlElement*> nodes = getAllTagsByName(doc.RootElement(), "AdditionalIncludeDirectories");
std::vector<TiXmlElement*> nodes = SolutionParserUtility::getAllTagsByName(doc.RootElement(), "AdditionalIncludeDirectories");
for (unsigned int j = 0; j < nodes.size(); j++)
{
@@ -310,27 +367,12 @@ std::vector<std::string> SolutionParserVisualStudio::findIncludePaths()
std::set<std::string> s(includePaths.begin(), includePaths.end());
includePaths.assign(s.begin(), s.end());
includePaths = resolveEnvironmentVariables(includePaths);
includePaths = SolutionParserUtility::resolveEnvironmentVariables(includePaths);
includePaths = makePathsAbsolute(includePaths);
return includePaths;
}
bool SolutionParserVisualStudio::checkValidFileExtension(const std::string& file, const std::vector<std::string>& validExtensions)
{
for (unsigned int i = 0; i < validExtensions.size(); i++)
{
size_t pos = file.find(validExtensions[i]);
if (pos != std::string::npos)
{
return true;
}
}
return false;
}
std::vector<std::string> SolutionParserVisualStudio::getProjectBlocks(const std::string& solution) const
{
std::vector<std::string> blocks;
@@ -420,300 +462,3 @@ std::vector<std::string> SolutionParserVisualStudio::seperateIncludePaths(const
return seperatedPaths;
}
TiXmlElement* SolutionParserVisualStudio::getFirstTagByName(TiXmlElement* root, const std::string& tag)
{
TiXmlElement* element = root;
while (element)
{
if (element == NULL)
{
}
std::string value = element->Value();
if (value == tag) // "ClInclude") // || value == "ClCompile")
{
if (element->Parent() != NULL)
{
return element; // ->Parent()->ToElement();
}
}
if (element->FirstChildElement() != NULL)
{
element = element->FirstChildElement();
}
else if (element->NextSiblingElement() != NULL)
{
element = element->NextSiblingElement();
}
else
{
if (element == NULL)
{
}
while (element->Parent()->ToElement() != NULL && element->Parent()->NextSiblingElement() == NULL)
{
TiXmlElement* newElement = element->Parent()->ToElement();
if (newElement == NULL)
{
}
element = newElement;
}
if (element->Parent() != NULL && element->Parent()->NextSiblingElement() != NULL)
{
element = element->Parent()->NextSiblingElement();
}
else
{
return NULL;
}
}
}
return NULL;
}
std::vector<TiXmlElement*> SolutionParserVisualStudio::getAllTagsByName(TiXmlElement* root, const std::string& tag)
{
std::vector<TiXmlElement*> nodes;
TiXmlElement* element = root;
while (element)
{
std::string value = element->Value();
if (value == tag)
{
nodes.push_back(element);
}
if (element->FirstChildElement() != NULL)
{
element = element->FirstChildElement();
}
else if (element->NextSiblingElement() != NULL)
{
element = element->NextSiblingElement();
}
else
{
if (element == NULL)
{
}
while (element->Parent()->ToElement() != NULL && element->Parent()->NextSiblingElement() == NULL)
{
TiXmlElement* newElement = element->Parent()->ToElement();
if (newElement == NULL)
{
}
element = newElement;
}
if (element->Parent() != NULL && element->Parent()->NextSiblingElement() != NULL)
{
element = element->Parent()->NextSiblingElement();
}
else
{
break;
}
}
}
return nodes;
}
TiXmlElement* SolutionParserVisualStudio::getFirstTagByNameWithAttribute(TiXmlElement* root, const std::string& tag, const std::string& attribute)
{
TiXmlElement* element = root;
while (element)
{
if (element == NULL)
{
}
std::string value = element->Value();
bool hasAttribute = false;
if (element->Attribute(attribute.c_str()) != NULL)
{
hasAttribute = true;
}
if (value == tag && hasAttribute) // "ClInclude") // || value == "ClCompile")
{
if (element->Parent() != NULL)
{
return element; // ->Parent()->ToElement();
}
}
if (element->FirstChildElement() != NULL)
{
element = element->FirstChildElement();
}
else if (element->NextSiblingElement() != NULL)
{
element = element->NextSiblingElement();
}
else
{
while (element->Parent()->ToElement() != NULL && element->Parent()->NextSiblingElement() == NULL)
{
TiXmlElement* newElement = element->Parent()->ToElement();
element = newElement;
}
if (element->Parent() != NULL && element->Parent()->NextSiblingElement() != NULL)
{
element = element->Parent()->NextSiblingElement();
}
else
{
return NULL;
}
}
}
return NULL;
}
std::vector<TiXmlElement*> SolutionParserVisualStudio::getAllTagsByNameWithAttribute(TiXmlElement* root, const std::string& tag, const std::string& attribute)
{
std::vector<TiXmlElement*> nodes;
TiXmlElement* element = root;
while (element)
{
std::string value = element->Value();
bool hasAttribute = false;
if (element->Attribute(attribute.c_str()) != NULL)
{
hasAttribute = true;
}
if (value == tag && hasAttribute)
{
nodes.push_back(element);
}
if (element->FirstChildElement() != NULL)
{
element = element->FirstChildElement();
}
else if (element->NextSiblingElement() != NULL)
{
element = element->NextSiblingElement();
}
else
{
while (element->Parent()->ToElement() != NULL && element->Parent()->NextSiblingElement() == NULL)
{
TiXmlElement* newElement = element->Parent()->ToElement();
element = newElement;
}
if (element->Parent() != NULL && element->Parent()->NextSiblingElement() != NULL)
{
element = element->Parent()->NextSiblingElement();
}
else
{
break;
}
}
}
return nodes;
}
std::vector<std::string> SolutionParserVisualStudio::resolveEnvironmentVariables(const std::vector<std::string>& paths)
{
std::vector<std::string> resolvedPaths;
for (unsigned int i = 0; i < paths.size(); i++)
{
resolvedPaths.push_back(findAndResolveEnvironmentVariable(paths[i]));
}
return resolvedPaths;
}
std::string SolutionParserVisualStudio::findAndResolveEnvironmentVariable(const std::string& path)
{
std::string resolvedPath;
size_t pos = path.find("$(");
if (pos != std::string::npos)
{
size_t endPos = path.substr(pos).find(")");
std::string envVariable = path.substr(pos+2, (endPos-2) - pos);
std::string envPath = getenv(envVariable.c_str());
std::string prePath = path.substr(0, pos);
std::string postPath = path.substr(endPos + 1);
resolvedPath = prePath + envPath + postPath;
}
else
{
resolvedPath = path;
}
return resolvedPath;
}
std::vector<std::string> SolutionParserVisualStudio::makePathsAbsolute(const std::vector<std::string>& paths)
{
std::vector<std::string> absolutePaths;
for (unsigned int i = 0; i < paths.size(); i++)
{
std::string path = paths[i];
boost::filesystem::path boostPath(path);
if (boostPath.is_relative())
{
path = m_solutionPath + path;
}
absolutePaths.push_back(path);
}
return absolutePaths;
}
std::vector<std::string> SolutionParserVisualStudio::makePathsCanonical(const std::vector<std::string>& paths)
{
std::vector<std::string> canonicalPaths;
for (unsigned int i = 0; i < paths.size(); i++)
{
try
{
boost::filesystem::path canonicalPath = boost::filesystem::canonical(boost::filesystem::path(paths[i]));
canonicalPaths.push_back(canonicalPath.string());
}
catch (std::exception& e)
{
std::string what = e.what();
LOG_WARNING_STREAM(<< e.what());
}
}
return canonicalPaths;
}
@@ -11,6 +11,8 @@ public:
SolutionParserVisualStudio();
virtual ~SolutionParserVisualStudio();
virtual std::string getToolID() const;
virtual std::string getSolutionName();
virtual std::vector<std::string> getProjects();
@@ -18,6 +20,13 @@ public:
virtual std::vector<std::string> getProjectItems();
virtual std::vector<std::string> getIncludePaths();
virtual ProjectSettings getProjectSettings(const std::string& solutionFilePath);
virtual std::string getIdeName() const;
virtual std::string getDescription() const;
virtual std::string getIconPath() const;
virtual std::string getFileExtension() const;
std::vector<std::string> getProjectItemsNonCanonical(); // for testing purposes, paths returned are non canonical, don't use if you don't know what that means
std::vector<std::string> getIncludePathsNonCanonical(); // for testing purposes, paths returned are non canonical, don't use if you don't know what that means
@@ -25,24 +34,11 @@ private:
std::vector<std::string> findProjectItems();
std::vector<std::string> findIncludePaths();
bool checkValidFileExtension(const std::string& file, const std::vector<std::string>& validExtensions);
std::vector<std::string> getProjectBlocks(const std::string& solution) const;
std::string getProjectFilePath(const std::string& projectBlock) const;
std::vector<std::string> seperateIncludePaths(const std::vector<std::string>& includePaths) const;
std::vector<std::string> seperateIncludePaths(const std::string& includePaths) const;
TiXmlElement* getFirstTagByName(TiXmlElement* root, const std::string& tag);
std::vector<TiXmlElement*> getAllTagsByName(TiXmlElement* root, const std::string& tag);
TiXmlElement* getFirstTagByNameWithAttribute(TiXmlElement* root, const std::string& tag, const std::string& attribute);
std::vector<TiXmlElement*> getAllTagsByNameWithAttribute(TiXmlElement* root, const std::string& tag, const std::string& attribute);
std::vector<std::string> resolveEnvironmentVariables(const std::vector<std::string>& paths);
std::string findAndResolveEnvironmentVariable(const std::string& path);
std::vector<std::string> makePathsAbsolute(const std::vector<std::string>& paths);
std::vector<std::string> makePathsCanonical(const std::vector<std::string>& paths);
};
#endif // SOLUTION_PARSER_VISUAL_STUDIO_H