logic: add include path validation to project settings

This commit is contained in:
malte_langkabel
2017-07-24 09:20:08 +02:00
parent faae66b304
commit bec7aa4aac
11 changed files with 411 additions and 138 deletions
+4
View File
@@ -76,6 +76,10 @@ add_files(
data/storage/StorageTransformationAnonymousTypedef.cpp
data/storage/StorageTransformationAnonymousTypedef.h
project/IncludeDirective.cpp
project/IncludeDirective.h
project/IncludeValidation.cpp
project/IncludeValidation.h
project/SourceGroupCxx.cpp
project/SourceGroupCxx.h
project/SourceGroupFactoryModuleCpp.cpp
+34
View File
@@ -0,0 +1,34 @@
#include "project/IncludeDirective.h"
IncludeDirective::IncludeDirective(
const FilePath& includedFilePath,
const FilePath& includingFilePath,
unsigned int lineNumber,
bool usesBrackets
)
: m_includedFilePath(includedFilePath)
, m_includingFilePath(includingFilePath)
, m_lineNumber(lineNumber)
, m_usesBrackets(usesBrackets)
{
}
FilePath IncludeDirective::getIncludedFile() const
{
return m_includedFilePath;
}
FilePath IncludeDirective::getIncludingFile() const
{
return m_includingFilePath;
}
std::string IncludeDirective::getDirective() const
{
return std::string("#include ") + (m_usesBrackets ? "<" : "\"") + m_includedFilePath.str() + (m_usesBrackets ? ">" : "\"");
}
unsigned int IncludeDirective::getLineNumber() const
{
return m_lineNumber;
}
+27
View File
@@ -0,0 +1,27 @@
#ifndef INCLUDE_DIRECTIVE_H
#define INCLUDE_DIRECTIVE_H
#include "utility/file/FilePath.h"
class IncludeDirective
{
public:
IncludeDirective(
const FilePath& includedFilePath,
const FilePath& includingFilePath,
unsigned int lineNumber,
bool usesBrackets);
FilePath getIncludedFile() const;
FilePath getIncludingFile() const;
std::string getDirective() const;
unsigned int getLineNumber() const;
private:
const FilePath m_includedFilePath;
const FilePath m_includingFilePath;
const unsigned int m_lineNumber;
bool m_usesBrackets;
};
#endif // INCLUDE_DIRECTIVE_H
+160
View File
@@ -0,0 +1,160 @@
#include "project/IncludeValidation.h"
#include "project/IncludeDirective.h"
#include "utility/file/FilePath.h"
#include "utility/text/TextAccess.h"
#include "utility/utility.h"
#include "utility/utilityString.h"
std::vector<IncludeDirective> IncludeValidation::getUnresolvedIncludeDirectives(
const std::vector<FilePath>& sourceFilePaths,
const std::vector<FilePath>& indexedPaths,
const std::vector<FilePath>& headerSearchDirectories,
size_t quantileCount, std::function<void(float)> progress
)
{
struct IncludeDirectiveComparator
{
bool operator()(const IncludeDirective& a, const IncludeDirective& b)
{
return a.getIncludedFile() < b.getIncludedFile();
}
};
std::set<std::string> processedFilePaths;
std::set<IncludeDirective, IncludeDirectiveComparator> unresolvedIncludeDirectives;
quantileCount = std::min(quantileCount, sourceFilePaths.size());
std::vector<std::vector<FilePath>> quantiles;
for (size_t i = 0; i < quantileCount; i++)
{
quantiles.push_back(std::vector<FilePath>());
}
for (size_t i = 0; i < sourceFilePaths.size(); i++)
{
quantiles[i%quantileCount].push_back(sourceFilePaths[i]);
}
for (size_t i = 0; i < quantiles.size(); i++)
{
const std::vector<FilePath>& quantile = quantiles[i];
progress(float(i) / quantiles.size());
std::set<FilePath> unprocessedFilePaths(quantile.begin(), quantile.end());
while (!unprocessedFilePaths.empty())
{
std::transform(unprocessedFilePaths.begin(), unprocessedFilePaths.end(), std::inserter(processedFilePaths, processedFilePaths.begin()), [](const FilePath& p){ return p.str(); });
std::set<FilePath> tempUnprocessedFilePaths;
for (const FilePath& filePath: unprocessedFilePaths)
{
for (const IncludeDirective& includeDirective: getIncludeDirectives(filePath))
{
const FilePath resolvedIncludePath = resolveIncludeDirective(includeDirective, headerSearchDirectories);
if (resolvedIncludePath.empty())
{
unresolvedIncludeDirectives.insert(includeDirective);
}
else if (processedFilePaths.find(resolvedIncludePath.str()) == processedFilePaths.end())
{
for (const FilePath& indexedPath: indexedPaths)
{
if (indexedPath.contains(resolvedIncludePath))
{
tempUnprocessedFilePaths.insert(resolvedIncludePath);
break;
}
}
}
}
}
unprocessedFilePaths = tempUnprocessedFilePaths;
}
}
std::vector<IncludeDirective> ret;
for (const IncludeDirective& directive: unresolvedIncludeDirectives)
{
ret.push_back(directive);
}
progress(1.0f);
return ret;
}
std::vector<IncludeDirective> IncludeValidation::getIncludeDirectives(const FilePath& filePath)
{
std::vector<IncludeDirective> includeDirectives;
if (filePath.exists())
{
std::shared_ptr<TextAccess> textAccess = TextAccess::createFromFile(filePath);
const std::vector<std::string> lines = textAccess->getAllLines();
for (size_t i = 0; i < lines.size(); i++)
{
const std::string lineTrimmedToHash = utility::trim(lines[i]);
if (utility::isPrefix("#", lineTrimmedToHash))
{
const std::string lineTrimmedToInclude = utility::trim(lineTrimmedToHash.substr(1));
if (utility::isPrefix("include", lineTrimmedToInclude))
{
std::string includeString = utility::substrBetween(lineTrimmedToInclude, "<", ">");
bool usesBrackets = true;
if (includeString.empty())
{
includeString = utility::substrBetween(lineTrimmedToInclude, "\"", "\"");
usesBrackets = false;
}
if (!includeString.empty())
{
// lines are 1 based
includeDirectives.push_back(IncludeDirective(FilePath(includeString), filePath, i + 1, usesBrackets));
}
}
}
}
}
return includeDirectives;
}
FilePath IncludeValidation::resolveIncludeDirective(const IncludeDirective& includeDirective, const std::vector<FilePath>& headerSearchDirectories)
{
{
// check for an absolute include path
if (includeDirective.getIncludedFile().exists())
{
return includeDirective.getIncludedFile();
}
}
{
// check for an include path relative to the including path
FilePath resolvedIncludePath = includeDirective.getIncludingFile().parentDirectory().concat(includeDirective.getIncludedFile());
if (resolvedIncludePath.exists())
{
return resolvedIncludePath;
}
}
{
// check for an include path relative to the header search directories
for (const FilePath& headerSearchDirectory: headerSearchDirectories)
{
FilePath resolvedIncludePath = headerSearchDirectory.concat(includeDirective.getIncludedFile());
if (resolvedIncludePath.exists())
{
return resolvedIncludePath;
}
}
}
return FilePath();
}
+24
View File
@@ -0,0 +1,24 @@
#ifndef INCLUDE_VALIDATION_H
#define INCLUDE_VALIDATION_H
#include <functional>
#include <set>
#include <vector>
class FilePath;
class IncludeDirective;
class IncludeValidation
{
public:
static std::vector<IncludeDirective> getUnresolvedIncludeDirectives(
const std::vector<FilePath>& sourceFilePaths,
const std::vector<FilePath>& indexedPaths,
const std::vector<FilePath>& headerSearchDirectories,
size_t quantileCount, std::function<void(float)> progress);
private:
static std::vector<IncludeDirective> getIncludeDirectives(const FilePath& filePath);
static FilePath resolveIncludeDirective(const IncludeDirective& includeDirective, const std::vector<FilePath>& headerSearchDirectories);
};
#endif // INCLUDE_VALIDATION_H