ui: added automatic include path detection for C/C++ Source Groups
This commit is contained in:
+1
@@ -0,0 +1 @@
|
|||||||
|
#include "a.h"
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
#include "a.h"
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
#include "../a.h"
|
||||||
@@ -128,13 +128,17 @@ bool FilePath::isAbsolute() const
|
|||||||
FilePath FilePath::getParentDirectory() const
|
FilePath FilePath::getParentDirectory() const
|
||||||
{
|
{
|
||||||
FilePath parentDirectory(m_path->parent_path());
|
FilePath parentDirectory(m_path->parent_path());
|
||||||
parentDirectory.m_checkedIsDirectory = true;
|
|
||||||
parentDirectory.m_isDirectory = true;
|
|
||||||
|
|
||||||
if (m_checkedExists && m_exists)
|
if (!parentDirectory.empty())
|
||||||
{
|
{
|
||||||
parentDirectory.m_checkedExists = true;
|
parentDirectory.m_checkedIsDirectory = true;
|
||||||
parentDirectory.m_exists = true;
|
parentDirectory.m_isDirectory = true;
|
||||||
|
|
||||||
|
if (m_checkedExists && m_exists)
|
||||||
|
{
|
||||||
|
parentDirectory.m_checkedExists = true;
|
||||||
|
parentDirectory.m_exists = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return parentDirectory;
|
return parentDirectory;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ std::vector<FilePath> FileSystem::getFilePathsFromDirectory(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (boost::filesystem::is_regular_file(*it) && ext.find(it->path().extension().string()) != ext.end())
|
if (boost::filesystem::is_regular_file(*it) && (ext.empty() || ext.find(it->path().extension().string()) != ext.end()))
|
||||||
{
|
{
|
||||||
files.push_back(FilePath(it->path().generic_string()));
|
files.push_back(FilePath(it->path().generic_string()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class FileSystem
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::vector<FilePath> getFilePathsFromDirectory(
|
static std::vector<FilePath> getFilePathsFromDirectory(
|
||||||
const FilePath& path, const std::vector<std::string>& extensions);
|
const FilePath& path, const std::vector<std::string>& extensions = {});
|
||||||
|
|
||||||
static FileInfo getFileInfoForPath(const FilePath& filePath);
|
static FileInfo getFileInfoForPath(const FilePath& filePath);
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,12 @@ std::shared_ptr<TextAccess> TextAccess::createFromFile(const FilePath& filePath)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<TextAccess> TextAccess::createFromString(const std::string& text)
|
std::shared_ptr<TextAccess> TextAccess::createFromString(const std::string& text, const FilePath& filePath)
|
||||||
{
|
{
|
||||||
std::shared_ptr<TextAccess> result(new TextAccess());
|
std::shared_ptr<TextAccess> result(new TextAccess());
|
||||||
|
|
||||||
result->m_lines = splitStringByLines(text);
|
result->m_lines = splitStringByLines(text);
|
||||||
|
result->m_filePath = filePath;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class TextAccess
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<TextAccess> createFromFile(const FilePath& filePath);
|
static std::shared_ptr<TextAccess> createFromFile(const FilePath& filePath);
|
||||||
static std::shared_ptr<TextAccess> createFromString(const std::string& text);
|
static std::shared_ptr<TextAccess> createFromString(const std::string& text, const FilePath& filePath = FilePath());
|
||||||
|
|
||||||
virtual ~TextAccess();
|
virtual ~TextAccess();
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ namespace utility
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
std::vector<T> toVector(const std::set<T>& d);
|
std::vector<T> toVector(const std::set<T>& d);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::set<T>toSet(const std::vector<T>& d);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void fillVectorWithElements(std::vector<T>& v, const T& arg);
|
void fillVectorWithElements(std::vector<T>& v, const T& arg);
|
||||||
|
|
||||||
@@ -191,6 +194,13 @@ std::vector<T> utility::toVector(const std::set<T>& d)
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::set<T> utility::toSet(const std::vector<T>& v)
|
||||||
|
{
|
||||||
|
std::set<T> s(v.begin(), v.end());
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void utility::fillVectorWithElements(std::vector<T>& v, const T& arg)
|
void utility::fillVectorWithElements(std::vector<T>& v, const T& arg)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -78,10 +78,6 @@ add_files(
|
|||||||
data/parser/cxx/utilityClang.cpp
|
data/parser/cxx/utilityClang.cpp
|
||||||
data/parser/cxx/utilityClang.h
|
data/parser/cxx/utilityClang.h
|
||||||
|
|
||||||
project/IncludeDirective.cpp
|
|
||||||
project/IncludeDirective.h
|
|
||||||
project/IncludeValidation.cpp
|
|
||||||
project/IncludeValidation.h
|
|
||||||
project/SourceGroupCxx.cpp
|
project/SourceGroupCxx.cpp
|
||||||
project/SourceGroupCxx.h
|
project/SourceGroupCxx.h
|
||||||
project/SourceGroupCxxCdb.cpp
|
project/SourceGroupCxxCdb.cpp
|
||||||
@@ -93,4 +89,8 @@ add_files(
|
|||||||
|
|
||||||
utility/CompilationDatabase.cpp
|
utility/CompilationDatabase.cpp
|
||||||
utility/CompilationDatabase.h
|
utility/CompilationDatabase.h
|
||||||
|
utility/IncludeDirective.cpp
|
||||||
|
utility/IncludeDirective.h
|
||||||
|
utility/IncludeProcessing.cpp
|
||||||
|
utility/IncludeProcessing.h
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,185 +0,0 @@
|
|||||||
#include "project/IncludeValidation.h"
|
|
||||||
|
|
||||||
#include <set>
|
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
#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::unordered_set<std::string> processedFilePaths;
|
|
||||||
std::set<IncludeDirective, IncludeDirectiveComparator> unresolvedIncludeDirectives;
|
|
||||||
|
|
||||||
quantileCount = std::max<size_t>(1, 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]);
|
|
||||||
}
|
|
||||||
|
|
||||||
OrderedCache<FilePath, FilePath> canonicalPathCache(
|
|
||||||
[](const FilePath& filePath)
|
|
||||||
{
|
|
||||||
return filePath.getCanonical();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
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> unprocessedFilePathsForNextIteration;
|
|
||||||
|
|
||||||
for (const FilePath& filePath: unprocessedFilePaths)
|
|
||||||
{
|
|
||||||
for (const IncludeDirective& includeDirective: getIncludeDirectives(filePath))
|
|
||||||
{
|
|
||||||
const FilePath resolvedIncludePath =
|
|
||||||
resolveIncludeDirective(includeDirective, headerSearchDirectories, canonicalPathCache).makeCanonical();
|
|
||||||
if (resolvedIncludePath.empty())
|
|
||||||
{
|
|
||||||
unresolvedIncludeDirectives.insert(includeDirective);
|
|
||||||
}
|
|
||||||
else if (processedFilePaths.find(resolvedIncludePath.str()) == processedFilePaths.end())
|
|
||||||
{
|
|
||||||
for (const FilePath& indexedPath: indexedPaths)
|
|
||||||
{
|
|
||||||
if (indexedPath.contains(resolvedIncludePath))
|
|
||||||
{
|
|
||||||
unprocessedFilePathsForNextIteration.insert(resolvedIncludePath);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unprocessedFilePaths = unprocessedFilePathsForNextIteration;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
OrderedCache<FilePath, FilePath>& canonicalPathCache
|
|
||||||
)
|
|
||||||
{
|
|
||||||
const FilePath includedFilePath = includeDirective.getIncludedFile();
|
|
||||||
|
|
||||||
{
|
|
||||||
// check for an absolute include path
|
|
||||||
if (includedFilePath.isAbsolute())
|
|
||||||
{
|
|
||||||
const FilePath resolvedIncludePath = canonicalPathCache.getValue(includedFilePath);
|
|
||||||
if (resolvedIncludePath.exists())
|
|
||||||
{
|
|
||||||
return includedFilePath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// check for an include path relative to the including path
|
|
||||||
const FilePath resolvedIncludePath = canonicalPathCache.getValue(includeDirective.getIncludingFile().getParentDirectory().concatenate(includedFilePath));
|
|
||||||
if (resolvedIncludePath.exists())
|
|
||||||
{
|
|
||||||
return resolvedIncludePath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// check for an include path relative to the header search directories
|
|
||||||
for (const FilePath& headerSearchDirectory: headerSearchDirectories)
|
|
||||||
{
|
|
||||||
const FilePath resolvedIncludePath = canonicalPathCache.getValue(headerSearchDirectory.getConcatenated(includedFilePath));
|
|
||||||
if (resolvedIncludePath.exists())
|
|
||||||
{
|
|
||||||
return resolvedIncludePath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FilePath();
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#ifndef INCLUDE_VALIDATION_H
|
|
||||||
#define INCLUDE_VALIDATION_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "utility/OrderedCache.h"
|
|
||||||
|
|
||||||
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,
|
|
||||||
OrderedCache<FilePath, FilePath>& canonicalPathCache
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_VALIDATION_H
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "project/IncludeDirective.h"
|
#include "utility/IncludeDirective.h"
|
||||||
|
|
||||||
IncludeDirective::IncludeDirective(
|
IncludeDirective::IncludeDirective(
|
||||||
const FilePath& includedFilePath,
|
const FilePath& includedFilePath,
|
||||||
@@ -0,0 +1,335 @@
|
|||||||
|
#include "utility/IncludeProcessing.h"
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#include "utility/IncludeDirective.h"
|
||||||
|
#include "utility/file/FilePath.h"
|
||||||
|
#include "utility/file/FileSystem.h"
|
||||||
|
#include "utility/text/TextAccess.h"
|
||||||
|
#include "utility/utility.h"
|
||||||
|
#include "utility/utilityString.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct IncludeDirectiveComparator
|
||||||
|
{
|
||||||
|
bool operator()(const IncludeDirective& a, const IncludeDirective& b)
|
||||||
|
{
|
||||||
|
return a.getIncludedFile() < b.getIncludedFile();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<std::vector<FilePath>> splitToQuantiles(
|
||||||
|
const std::set<FilePath>& sourceFilePaths,
|
||||||
|
const size_t desiredQuantileCount)
|
||||||
|
{
|
||||||
|
size_t quantileCount = std::max<size_t>(1, std::min(desiredQuantileCount, sourceFilePaths.size()));
|
||||||
|
|
||||||
|
std::vector<std::vector<FilePath>> quantiles;
|
||||||
|
for (size_t i = 0; i < quantileCount; i++)
|
||||||
|
{
|
||||||
|
quantiles.push_back(std::vector<FilePath>());
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (const FilePath& sourceFilePath : sourceFilePaths)
|
||||||
|
{
|
||||||
|
quantiles[i % quantileCount].push_back(sourceFilePath);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return quantiles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<IncludeDirective> IncludeProcessing::getUnresolvedIncludeDirectives(
|
||||||
|
const std::set<FilePath>& sourceFilePaths,
|
||||||
|
const std::set<FilePath>& indexedPaths,
|
||||||
|
const std::set<FilePath>& headerSearchDirectories,
|
||||||
|
const size_t desiredQuantileCount, std::function<void(float)> progress
|
||||||
|
)
|
||||||
|
{
|
||||||
|
std::unordered_set<std::string> processedFilePaths;
|
||||||
|
std::set<IncludeDirective, IncludeDirectiveComparator> unresolvedIncludeDirectives;
|
||||||
|
|
||||||
|
std::vector<std::vector<FilePath>> quantiles = splitToQuantiles(sourceFilePaths, desiredQuantileCount);
|
||||||
|
|
||||||
|
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> unprocessedFilePathsForNextIteration;
|
||||||
|
|
||||||
|
for (const FilePath& filePath: unprocessedFilePaths)
|
||||||
|
{
|
||||||
|
for (const IncludeDirective& includeDirective: getIncludeDirectives(filePath))
|
||||||
|
{
|
||||||
|
const FilePath resolvedIncludePath = resolveIncludeDirective(includeDirective, headerSearchDirectories).makeCanonical();
|
||||||
|
if (resolvedIncludePath.empty())
|
||||||
|
{
|
||||||
|
unresolvedIncludeDirectives.insert(includeDirective);
|
||||||
|
}
|
||||||
|
else if (processedFilePaths.find(resolvedIncludePath.str()) == processedFilePaths.end())
|
||||||
|
{
|
||||||
|
for (const FilePath& indexedPath: indexedPaths)
|
||||||
|
{
|
||||||
|
if (indexedPath.contains(resolvedIncludePath))
|
||||||
|
{
|
||||||
|
unprocessedFilePathsForNextIteration.insert(resolvedIncludePath);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unprocessedFilePaths = unprocessedFilePathsForNextIteration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<IncludeDirective> ret;
|
||||||
|
|
||||||
|
for (const IncludeDirective& directive: unresolvedIncludeDirectives)
|
||||||
|
{
|
||||||
|
ret.push_back(directive);
|
||||||
|
}
|
||||||
|
|
||||||
|
progress(1.0f);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<FilePath> IncludeProcessing::getHeaderSearchDirectories(
|
||||||
|
const std::set<FilePath>& sourceFilePaths,
|
||||||
|
const std::set<FilePath>& searchedPaths,
|
||||||
|
const size_t desiredQuantileCount, std::function<void(float)> progress
|
||||||
|
)
|
||||||
|
{
|
||||||
|
progress(0.0f);
|
||||||
|
|
||||||
|
std::map<std::string, std::set<FilePath>> existingFilePaths;
|
||||||
|
for (const FilePath& searchedPath : searchedPaths)
|
||||||
|
{
|
||||||
|
if (searchedPath.isDirectory())
|
||||||
|
{
|
||||||
|
for (const FilePath& filePath : FileSystem::getFilePathsFromDirectory(searchedPath.getCanonical()))
|
||||||
|
{
|
||||||
|
existingFilePaths[filePath.fileName()].insert(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
existingFilePaths[searchedPath.fileName()].insert(searchedPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<FilePath> headerSearchDirectories;
|
||||||
|
std::unordered_set<std::string> processedFilePaths;
|
||||||
|
std::vector<std::vector<FilePath>> quantiles = splitToQuantiles(sourceFilePaths, desiredQuantileCount);
|
||||||
|
|
||||||
|
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> unprocessedFilePathsForNextIteration;
|
||||||
|
|
||||||
|
for (const FilePath& unprocessedFilePath : unprocessedFilePaths)
|
||||||
|
{
|
||||||
|
for (const IncludeDirective& includeDirective : getIncludeDirectives(unprocessedFilePath))
|
||||||
|
{
|
||||||
|
const FilePath includedFilePath = includeDirective.getIncludedFile();
|
||||||
|
|
||||||
|
FilePath foundIncludedPath;
|
||||||
|
if (includedFilePath.isAbsolute())
|
||||||
|
{
|
||||||
|
foundIncludedPath = includedFilePath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const FilePath relativeToIncludingPath = includeDirective.getIncludingFile().getParentDirectory().concatenate(includedFilePath);
|
||||||
|
if (relativeToIncludingPath.exists())
|
||||||
|
{
|
||||||
|
foundIncludedPath = relativeToIncludingPath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::map<std::string, std::set<FilePath>>::const_iterator it = existingFilePaths.find(includedFilePath.fileName());
|
||||||
|
if (it != existingFilePaths.end())
|
||||||
|
{
|
||||||
|
// TODO: handle the case where a file can be found by two different paths
|
||||||
|
for (FilePath existingFilePath : it->second)
|
||||||
|
{
|
||||||
|
existingFilePath = existingFilePath.getParentDirectory();
|
||||||
|
bool ok = true;
|
||||||
|
{
|
||||||
|
FilePath tempIncludedFilePath = includedFilePath.getParentDirectory();
|
||||||
|
while (!tempIncludedFilePath.empty())
|
||||||
|
{
|
||||||
|
if (tempIncludedFilePath.fileName() == "..")
|
||||||
|
{
|
||||||
|
std::vector<FilePath> subDirectories = FileSystem::getDirectSubDirectories(existingFilePath);
|
||||||
|
if (!subDirectories.empty())
|
||||||
|
{
|
||||||
|
existingFilePath = subDirectories.front();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
existingFilePath = existingFilePath.getParentDirectory();
|
||||||
|
}
|
||||||
|
tempIncludedFilePath = tempIncludedFilePath.getParentDirectory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
foundIncludedPath = existingFilePath.getConcatenated(includedFilePath);
|
||||||
|
if (foundIncludedPath.exists())
|
||||||
|
{
|
||||||
|
headerSearchDirectories.insert(existingFilePath);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (foundIncludedPath.exists())
|
||||||
|
{
|
||||||
|
if (processedFilePaths.find(foundIncludedPath.str()) == processedFilePaths.end())
|
||||||
|
{
|
||||||
|
for (const FilePath& searchedPath : searchedPaths)
|
||||||
|
{
|
||||||
|
if (searchedPath.contains(foundIncludedPath))
|
||||||
|
{
|
||||||
|
unprocessedFilePathsForNextIteration.insert(foundIncludedPath);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unprocessedFilePaths = unprocessedFilePathsForNextIteration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
progress(1.0f);
|
||||||
|
|
||||||
|
return headerSearchDirectories;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<IncludeDirective> IncludeProcessing::getIncludeDirectives(const FilePath& filePath)
|
||||||
|
{
|
||||||
|
if (filePath.exists())
|
||||||
|
{
|
||||||
|
return getIncludeDirectives(TextAccess::createFromFile(filePath));
|
||||||
|
}
|
||||||
|
return std::vector<IncludeDirective>();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<IncludeDirective> IncludeProcessing::getIncludeDirectives(std::shared_ptr<TextAccess> textAccess)
|
||||||
|
{
|
||||||
|
std::vector<IncludeDirective> includeDirectives;
|
||||||
|
|
||||||
|
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), textAccess->getFilePath(), i + 1, usesBrackets));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return includeDirectives;
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePath IncludeProcessing::resolveIncludeDirective(
|
||||||
|
const IncludeDirective& includeDirective,
|
||||||
|
const std::set<FilePath>& headerSearchDirectories
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const FilePath includedFilePath = includeDirective.getIncludedFile();
|
||||||
|
|
||||||
|
{
|
||||||
|
// check for an absolute include path
|
||||||
|
if (includedFilePath.isAbsolute())
|
||||||
|
{
|
||||||
|
const FilePath resolvedIncludePath = includedFilePath;
|
||||||
|
if (resolvedIncludePath.exists())
|
||||||
|
{
|
||||||
|
return includedFilePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// check for an include path relative to the including path
|
||||||
|
const FilePath resolvedIncludePath = includeDirective.getIncludingFile().getParentDirectory().concatenate(includedFilePath);
|
||||||
|
if (resolvedIncludePath.exists())
|
||||||
|
{
|
||||||
|
return resolvedIncludePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// check for an include path relative to the header search directories
|
||||||
|
for (const FilePath& headerSearchDirectory: headerSearchDirectories)
|
||||||
|
{
|
||||||
|
const FilePath resolvedIncludePath = headerSearchDirectory.getConcatenated(includedFilePath);
|
||||||
|
if (resolvedIncludePath.exists())
|
||||||
|
{
|
||||||
|
return resolvedIncludePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FilePath();
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#ifndef INCLUDE_PROCESSING_H
|
||||||
|
#define INCLUDE_PROCESSING_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "utility/OrderedCache.h"
|
||||||
|
|
||||||
|
class FilePath;
|
||||||
|
class IncludeDirective;
|
||||||
|
class TextAccess;
|
||||||
|
|
||||||
|
class IncludeProcessing
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static std::vector<IncludeDirective> getUnresolvedIncludeDirectives(
|
||||||
|
const std::set<FilePath>& sourceFilePaths,
|
||||||
|
const std::set<FilePath>& indexedPaths,
|
||||||
|
const std::set<FilePath>& headerSearchDirectories,
|
||||||
|
size_t quantileCount, std::function<void(float)> progress
|
||||||
|
);
|
||||||
|
|
||||||
|
static std::set<FilePath> getHeaderSearchDirectories(
|
||||||
|
const std::set<FilePath>& sourceFilePaths,
|
||||||
|
const std::set<FilePath>& searchedPaths,
|
||||||
|
const size_t desiredQuantileCount, std::function<void(float)> progress
|
||||||
|
);
|
||||||
|
|
||||||
|
static std::vector<IncludeDirective> getIncludeDirectives(const FilePath& filePath);
|
||||||
|
|
||||||
|
static std::vector<IncludeDirective> getIncludeDirectives(std::shared_ptr<TextAccess> textAccess);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static FilePath resolveIncludeDirective(
|
||||||
|
const IncludeDirective& includeDirective,
|
||||||
|
const std::set<FilePath>& headerSearchDirectories
|
||||||
|
);
|
||||||
|
|
||||||
|
IncludeProcessing() = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // INCLUDE_PROCESSING_H
|
||||||
@@ -225,6 +225,8 @@ add_files(
|
|||||||
qt/window/QtLicenseWindow.h
|
qt/window/QtLicenseWindow.h
|
||||||
qt/window/QtMainWindow.cpp
|
qt/window/QtMainWindow.cpp
|
||||||
qt/window/QtMainWindow.h
|
qt/window/QtMainWindow.h
|
||||||
|
qt/window/QtPathListDialog.cpp
|
||||||
|
qt/window/QtPathListDialog.h
|
||||||
qt/window/QtPreferencesWindow.cpp
|
qt/window/QtPreferencesWindow.cpp
|
||||||
qt/window/QtPreferencesWindow.h
|
qt/window/QtPreferencesWindow.h
|
||||||
qt/window/QtSelectPathsDialog.cpp
|
qt/window/QtSelectPathsDialog.cpp
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ void QtProgressBar::showProgress(size_t percent)
|
|||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t QtProgressBar::getProgress() const
|
||||||
|
{
|
||||||
|
return m_percent;
|
||||||
|
}
|
||||||
|
|
||||||
void QtProgressBar::showUnknownProgressAnimated()
|
void QtProgressBar::showUnknownProgressAnimated()
|
||||||
{
|
{
|
||||||
start();
|
start();
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ public:
|
|||||||
QtProgressBar(QWidget* parent = nullptr);
|
QtProgressBar(QWidget* parent = nullptr);
|
||||||
|
|
||||||
void showProgress(size_t percent);
|
void showProgress(size_t percent);
|
||||||
|
size_t getProgress() const;
|
||||||
|
|
||||||
void showUnknownProgressAnimated();
|
void showUnknownProgressAnimated();
|
||||||
|
|
||||||
|
|||||||
@@ -58,11 +58,10 @@ void QtDialogView::hideUnknownProgressDialog()
|
|||||||
|
|
||||||
void QtDialogView::showProgressDialog(const std::string& title, const std::string& message, int progress)
|
void QtDialogView::showProgressDialog(const std::string& title, const std::string& message, int progress)
|
||||||
{
|
{
|
||||||
MessageStatus(title + ": " + message + " [" + std::to_string(progress) + "%]", false, true).dispatch();
|
|
||||||
|
|
||||||
m_onQtThread(
|
m_onQtThread(
|
||||||
[=]()
|
[=]()
|
||||||
{
|
{
|
||||||
|
bool sendStatusMessage = true;
|
||||||
QtIndexingDialog* window = dynamic_cast<QtIndexingDialog*>(m_windowStack.getTopWindow());
|
QtIndexingDialog* window = dynamic_cast<QtIndexingDialog*>(m_windowStack.getTopWindow());
|
||||||
if (!window || window->getType() != QtIndexingDialog::DIALOG_PROGRESS)
|
if (!window || window->getType() != QtIndexingDialog::DIALOG_PROGRESS)
|
||||||
{
|
{
|
||||||
@@ -71,6 +70,19 @@ void QtDialogView::showProgressDialog(const std::string& title, const std::strin
|
|||||||
window = createWindow<QtIndexingDialog>();
|
window = createWindow<QtIndexingDialog>();
|
||||||
window->setupProgress();
|
window->setupProgress();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sendStatusMessage = (
|
||||||
|
window->getTitle() != title ||
|
||||||
|
window->getMessage() != message ||
|
||||||
|
window->getProgress() != progress
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sendStatusMessage)
|
||||||
|
{
|
||||||
|
MessageStatus(title + ": " + message + " [" + std::to_string(progress) + "%]", false, true).dispatch();
|
||||||
|
}
|
||||||
|
|
||||||
window->updateTitle(title.c_str());
|
window->updateTitle(title.c_str());
|
||||||
window->updateMessage(message.c_str());
|
window->updateMessage(message.c_str());
|
||||||
|
|||||||
@@ -273,15 +273,29 @@ void QtIndexingDialog::updateMessage(QString message)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtIndexingDialog::updateProgress(int progress)
|
std::string QtIndexingDialog::getMessage() const
|
||||||
{
|
{
|
||||||
int percent = std::min(std::max(progress, 0), 100);
|
if (m_messageLabel)
|
||||||
|
{
|
||||||
|
return m_messageLabel->text().toStdString();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtIndexingDialog::updateProgress(size_t progress)
|
||||||
|
{
|
||||||
|
size_t percent = std::min<size_t>(std::max<size_t>(progress, 0), 100);
|
||||||
|
|
||||||
m_progressBar->showProgress(percent);
|
m_progressBar->showProgress(percent);
|
||||||
m_percentLabel->setText(QString::number(percent) + "% Progress");
|
m_percentLabel->setText(QString::number(percent) + "% Progress");
|
||||||
setGeometries();
|
setGeometries();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t QtIndexingDialog::getProgress() const
|
||||||
|
{
|
||||||
|
return m_progressBar->getProgress();
|
||||||
|
}
|
||||||
|
|
||||||
void QtIndexingDialog::updateIndexingProgress(size_t fileCount, size_t totalFileCount, std::string sourcePath)
|
void QtIndexingDialog::updateIndexingProgress(size_t fileCount, size_t totalFileCount, std::string sourcePath)
|
||||||
{
|
{
|
||||||
updateMessage(QString::number(fileCount) + "/" + QString::number(totalFileCount) + " File" + (totalFileCount > 1 ? "s" : ""));
|
updateMessage(QString::number(fileCount) + "/" + QString::number(totalFileCount) + " File" + (totalFileCount > 1 ? "s" : ""));
|
||||||
|
|||||||
@@ -48,7 +48,9 @@ public:
|
|||||||
void setupProgress();
|
void setupProgress();
|
||||||
|
|
||||||
void updateMessage(QString message);
|
void updateMessage(QString message);
|
||||||
void updateProgress(int progress);
|
std::string getMessage() const;
|
||||||
|
void updateProgress(size_t progress);
|
||||||
|
size_t getProgress() const;
|
||||||
void updateIndexingProgress(size_t fileCount, size_t totalFileCount, std::string sourcePath);
|
void updateIndexingProgress(size_t fileCount, size_t totalFileCount, std::string sourcePath);
|
||||||
void updateErrorCount(size_t errorCount, size_t fatalCount);
|
void updateErrorCount(size_t errorCount, size_t fatalCount);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
#include "qt/window/QtPathListDialog.h"
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
#include "qt/element/QtDirectoryListBox.h"
|
||||||
|
|
||||||
|
QtPathListDialog::QtPathListDialog(const QString& title, const QString& description, QWidget* parent)
|
||||||
|
: QtWindow(parent)
|
||||||
|
, m_title(title)
|
||||||
|
, m_description(description)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize QtPathListDialog::sizeHint() const
|
||||||
|
{
|
||||||
|
return QSize(550, 550);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtPathListDialog::setRelativeRootDirectory(const FilePath& dir)
|
||||||
|
{
|
||||||
|
m_pathList->setRelativeRootDirectory(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtPathListDialog::setPaths(const std::vector<FilePath>& paths, bool readOnly)
|
||||||
|
{
|
||||||
|
m_pathList->setList(paths, readOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<FilePath> QtPathListDialog::getPaths()
|
||||||
|
{
|
||||||
|
return m_pathList->getList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtPathListDialog::populateWindow(QWidget* widget)
|
||||||
|
{
|
||||||
|
QVBoxLayout* layout = new QVBoxLayout();
|
||||||
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
|
QLabel* description = new QLabel(m_description);
|
||||||
|
description->setObjectName("description");
|
||||||
|
description->setWordWrap(true);
|
||||||
|
layout->addWidget(description);
|
||||||
|
|
||||||
|
m_pathList = new QtDirectoryListBox(this, m_title);
|
||||||
|
layout->addWidget(m_pathList);
|
||||||
|
|
||||||
|
widget->setLayout(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtPathListDialog::windowReady()
|
||||||
|
{
|
||||||
|
updateNextButton("Save");
|
||||||
|
updateCloseButton("Cancel");
|
||||||
|
|
||||||
|
setPreviousVisible(false);
|
||||||
|
|
||||||
|
updateTitle(m_title);
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
#ifndef QT_PATH_LIST_DIALOG_H
|
||||||
|
#define QT_PATH_LIST_DIALOG_H
|
||||||
|
|
||||||
|
#include "qt/window/QtWindow.h"
|
||||||
|
|
||||||
|
class FilePath;
|
||||||
|
class QtDirectoryListBox;
|
||||||
|
|
||||||
|
class QtPathListDialog
|
||||||
|
: public QtWindow
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
QtPathListDialog(const QString& title, const QString& description, QWidget* parent = 0);
|
||||||
|
|
||||||
|
QSize sizeHint() const override;
|
||||||
|
|
||||||
|
void setRelativeRootDirectory(const FilePath& dir);
|
||||||
|
void setPaths(const std::vector<FilePath>& paths, bool readOnly = false);
|
||||||
|
std::vector<FilePath> getPaths();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void populateWindow(QWidget* widget) override;
|
||||||
|
void windowReady() override;
|
||||||
|
|
||||||
|
QString m_title;
|
||||||
|
QString m_description;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QtDirectoryListBox* m_pathList;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QT_PATH_LIST_DIALOG_H
|
||||||
@@ -28,7 +28,6 @@ protected:
|
|||||||
QString m_description;
|
QString m_description;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QPlainTextEdit* m_text;
|
QPlainTextEdit* m_text;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -213,6 +213,15 @@ void QtWindow::updateTitle(QString title)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string QtWindow::getTitle() const
|
||||||
|
{
|
||||||
|
if (m_title)
|
||||||
|
{
|
||||||
|
return m_title->text().toStdString();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
void QtWindow::updateSubTitle(QString subTitle)
|
void QtWindow::updateSubTitle(QString subTitle)
|
||||||
{
|
{
|
||||||
if (m_subTitle)
|
if (m_subTitle)
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public:
|
|||||||
void moveToCenter();
|
void moveToCenter();
|
||||||
|
|
||||||
void updateTitle(QString title);
|
void updateTitle(QString title);
|
||||||
|
std::string getTitle() const;
|
||||||
void updateSubTitle(QString subTitle);
|
void updateSubTitle(QString subTitle);
|
||||||
|
|
||||||
void updateNextButton(QString text);
|
void updateNextButton(QString text);
|
||||||
|
|||||||
@@ -9,10 +9,11 @@
|
|||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "component/view/DialogView.h"
|
#include "component/view/DialogView.h"
|
||||||
#include "data/indexer/IndexerCommandCxxCdb.h"
|
#include "data/indexer/IndexerCommandCxxCdb.h"
|
||||||
#include "project/IncludeDirective.h"
|
#include "utility/IncludeDirective.h"
|
||||||
#include "project/IncludeValidation.h"
|
#include "utility/IncludeProcessing.h"
|
||||||
#include "qt/element/QtDirectoryListBox.h"
|
#include "qt/element/QtDirectoryListBox.h"
|
||||||
#include "qt/view/QtDialogView.h"
|
#include "qt/view/QtDialogView.h"
|
||||||
|
#include "qt/window/QtPathListDialog.h"
|
||||||
#include "qt/window/QtSelectPathsDialog.h"
|
#include "qt/window/QtSelectPathsDialog.h"
|
||||||
#include "settings/ApplicationSettings.h"
|
#include "settings/ApplicationSettings.h"
|
||||||
#include "settings/SourceGroupSettingsCxxCdb.h"
|
#include "settings/SourceGroupSettingsCxxCdb.h"
|
||||||
@@ -23,6 +24,7 @@
|
|||||||
#include "utility/utility.h"
|
#include "utility/utility.h"
|
||||||
#include "utility/utilityFile.h"
|
#include "utility/utilityFile.h"
|
||||||
#include "utility/utilityPathDetection.h"
|
#include "utility/utilityPathDetection.h"
|
||||||
|
#include "utility/utilityString.h"
|
||||||
|
|
||||||
QtProjectWizzardContentPaths::QtProjectWizzardContentPaths(
|
QtProjectWizzardContentPaths::QtProjectWizzardContentPaths(
|
||||||
std::shared_ptr<SourceGroupSettings> settings, QtProjectWizzardWindow* window
|
std::shared_ptr<SourceGroupSettings> settings, QtProjectWizzardWindow* window
|
||||||
@@ -429,6 +431,8 @@ QtProjectWizzardContentPathsHeaderSearch::QtProjectWizzardContentPathsHeaderSear
|
|||||||
: QtProjectWizzardContentPaths(settings, window)
|
: QtProjectWizzardContentPaths(settings, window)
|
||||||
, m_showValidationResultFunctor(std::bind(
|
, m_showValidationResultFunctor(std::bind(
|
||||||
&QtProjectWizzardContentPathsHeaderSearch::showValidationResult, this, std::placeholders::_1))
|
&QtProjectWizzardContentPathsHeaderSearch::showValidationResult, this, std::placeholders::_1))
|
||||||
|
, m_showDetectedIncludesResultFunctor(std::bind(
|
||||||
|
&QtProjectWizzardContentPathsHeaderSearch::showDetectedIncludesResult, this, std::placeholders::_1))
|
||||||
, m_isCdb(isCDB)
|
, m_isCdb(isCDB)
|
||||||
{
|
{
|
||||||
setTitleString(m_isCdb ? "Additional Include Paths" : "Include Paths");
|
setTitleString(m_isCdb ? "Additional Include Paths" : "Include Paths");
|
||||||
@@ -454,11 +458,18 @@ void QtProjectWizzardContentPathsHeaderSearch::populate(QGridLayout* layout, int
|
|||||||
|
|
||||||
if (!m_isCdb)
|
if (!m_isCdb)
|
||||||
{
|
{
|
||||||
QPushButton* button = new QPushButton("validate include directives");
|
{
|
||||||
button->setObjectName("windowButton");
|
QPushButton* detectionButton = new QPushButton("auto-detect");
|
||||||
connect(button, &QPushButton::clicked, this, &QtProjectWizzardContentPathsHeaderSearch::validateButtonClicked);
|
detectionButton->setObjectName("windowButton");
|
||||||
|
connect(detectionButton, &QPushButton::clicked, this, &QtProjectWizzardContentPathsHeaderSearch::detectIncludesButtonClicked);
|
||||||
layout->addWidget(button, row, QtProjectWizzardWindow::BACK_COL, Qt::AlignRight | Qt::AlignTop);
|
layout->addWidget(detectionButton, row, QtProjectWizzardWindow::BACK_COL, Qt::AlignLeft | Qt::AlignTop);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
QPushButton* validateionButton = new QPushButton("validate include directives");
|
||||||
|
validateionButton->setObjectName("windowButton");
|
||||||
|
connect(validateionButton, &QPushButton::clicked, this, &QtProjectWizzardContentPathsHeaderSearch::validateIncludesButtonClicked);
|
||||||
|
layout->addWidget(validateionButton, row, QtProjectWizzardWindow::BACK_COL, Qt::AlignRight | Qt::AlignTop);
|
||||||
|
}
|
||||||
row++;
|
row++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -486,7 +497,30 @@ bool QtProjectWizzardContentPathsHeaderSearch::isScrollAble() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtProjectWizzardContentPathsHeaderSearch::validateButtonClicked()
|
void QtProjectWizzardContentPathsHeaderSearch::detectIncludesButtonClicked()
|
||||||
|
{
|
||||||
|
m_window->saveContent();
|
||||||
|
|
||||||
|
m_pathsDialog = std::make_shared<QtPathListDialog>(
|
||||||
|
"Detect Include Paths",
|
||||||
|
"<p>Automatically search the paths provided below for additional include paths that "
|
||||||
|
"can be used to resolve include directives within your source code.</p>"
|
||||||
|
"<p>The indexed paths will be searched by default but you can add further paths if required.</p>"
|
||||||
|
);
|
||||||
|
|
||||||
|
m_pathsDialog->setup();
|
||||||
|
m_pathsDialog->updateNextButton("Next");
|
||||||
|
m_pathsDialog->setCloseVisible(true);
|
||||||
|
|
||||||
|
m_pathsDialog->setRelativeRootDirectory(m_settings->getProjectDirectoryPath());
|
||||||
|
m_pathsDialog->setPaths(m_settings->getSourcePaths(), true);
|
||||||
|
m_pathsDialog->showWindow();
|
||||||
|
|
||||||
|
connect(m_pathsDialog.get(), &QtPathListDialog::finished, this, &QtProjectWizzardContentPathsHeaderSearch::finishedSelectDetectIncludesRootPathsDialog);
|
||||||
|
connect(m_pathsDialog.get(), &QtPathListDialog::canceled, this, &QtProjectWizzardContentPathsHeaderSearch::closedPathsDialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtProjectWizzardContentPathsHeaderSearch::validateIncludesButtonClicked()
|
||||||
{
|
{
|
||||||
// TODO: regard Force Includes here, too!
|
// TODO: regard Force Includes here, too!
|
||||||
m_window->saveContent();
|
m_window->saveContent();
|
||||||
@@ -497,7 +531,7 @@ void QtProjectWizzardContentPathsHeaderSearch::validateButtonClicked()
|
|||||||
{
|
{
|
||||||
std::shared_ptr<DialogView> dialogView = Application::getInstance()->getDialogView();
|
std::shared_ptr<DialogView> dialogView = Application::getInstance()->getDialogView();
|
||||||
|
|
||||||
std::vector<FilePath> sourceFilePaths;
|
std::set<FilePath> sourceFilePaths;
|
||||||
std::vector<FilePath> indexedFilePaths;
|
std::vector<FilePath> indexedFilePaths;
|
||||||
std::vector<FilePath> headerSearchPaths;
|
std::vector<FilePath> headerSearchPaths;
|
||||||
|
|
||||||
@@ -514,7 +548,7 @@ void QtProjectWizzardContentPathsHeaderSearch::validateButtonClicked()
|
|||||||
m_settings->getExcludePathsExpandedAndAbsolute(),
|
m_settings->getExcludePathsExpandedAndAbsolute(),
|
||||||
m_settings->getSourceExtensions()
|
m_settings->getSourceExtensions()
|
||||||
);
|
);
|
||||||
sourceFilePaths = utility::toVector(fileManager.getAllSourceFilePaths());
|
sourceFilePaths = fileManager.getAllSourceFilePaths();
|
||||||
|
|
||||||
headerSearchPaths = ApplicationSettings::getInstance()->getHeaderSearchPathsExpanded();
|
headerSearchPaths = ApplicationSettings::getInstance()->getHeaderSearchPathsExpanded();
|
||||||
|
|
||||||
@@ -531,10 +565,10 @@ void QtProjectWizzardContentPathsHeaderSearch::validateButtonClicked()
|
|||||||
dialogView->hideProgressDialog();
|
dialogView->hideProgressDialog();
|
||||||
});
|
});
|
||||||
|
|
||||||
unresolvedIncludes = IncludeValidation::getUnresolvedIncludeDirectives(
|
unresolvedIncludes = IncludeProcessing::getUnresolvedIncludeDirectives(
|
||||||
sourceFilePaths,
|
sourceFilePaths,
|
||||||
indexedFilePaths,
|
utility::toSet(indexedFilePaths),
|
||||||
headerSearchPaths,
|
utility::toSet(headerSearchPaths),
|
||||||
log2(sourceFilePaths.size()),
|
log2(sourceFilePaths.size()),
|
||||||
[&](const float progress)
|
[&](const float progress)
|
||||||
{
|
{
|
||||||
@@ -549,6 +583,147 @@ void QtProjectWizzardContentPathsHeaderSearch::validateButtonClicked()
|
|||||||
}).detach();
|
}).detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QtProjectWizzardContentPathsHeaderSearch::finishedSelectDetectIncludesRootPathsDialog()
|
||||||
|
{
|
||||||
|
// TODO: regard Force Includes here, too!
|
||||||
|
const std::vector<FilePath> searchedPaths = m_settings->makePathsExpandedAndAbsolute(m_pathsDialog->getPaths());
|
||||||
|
|
||||||
|
closedPathsDialog();
|
||||||
|
|
||||||
|
std::thread([=]()
|
||||||
|
{
|
||||||
|
std::set<FilePath> detectedHeaderSearchPaths;
|
||||||
|
{
|
||||||
|
std::shared_ptr<QtDialogView> dialogView = std::dynamic_pointer_cast<QtDialogView>(Application::getInstance()->getDialogView());
|
||||||
|
|
||||||
|
std::set<FilePath> sourceFilePaths;
|
||||||
|
|
||||||
|
{
|
||||||
|
dialogView->setParentWindow(m_window);
|
||||||
|
dialogView->showUnknownProgressDialog("Processing", "Gathering Source Files");
|
||||||
|
ScopedFunctor dialogHider([&dialogView]() {
|
||||||
|
dialogView->hideUnknownProgressDialog();
|
||||||
|
});
|
||||||
|
|
||||||
|
FileManager fileManager;
|
||||||
|
fileManager.update(
|
||||||
|
m_settings->getSourcePathsExpandedAndAbsolute(),
|
||||||
|
m_settings->getExcludePathsExpandedAndAbsolute(),
|
||||||
|
m_settings->getSourceExtensions()
|
||||||
|
);
|
||||||
|
sourceFilePaths = fileManager.getAllSourceFilePaths();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
dialogView->setParentWindow(m_window);
|
||||||
|
ScopedFunctor dialogHider([&dialogView]() {
|
||||||
|
dialogView->hideProgressDialog();
|
||||||
|
});
|
||||||
|
|
||||||
|
detectedHeaderSearchPaths = IncludeProcessing::getHeaderSearchDirectories(
|
||||||
|
sourceFilePaths,
|
||||||
|
utility::toSet(searchedPaths),
|
||||||
|
log2(sourceFilePaths.size()),
|
||||||
|
[&](const float progress)
|
||||||
|
{
|
||||||
|
Application::getInstance()->getDialogView()->showProgressDialog(
|
||||||
|
"Processing", std::to_string(int(progress * sourceFilePaths.size())) + " Files", int(progress * 100.0f)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_showDetectedIncludesResultFunctor(detectedHeaderSearchPaths);
|
||||||
|
}).detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtProjectWizzardContentPathsHeaderSearch::finishedAcceptDetectedIncludePathsDialog()
|
||||||
|
{
|
||||||
|
const std::vector<std::string> detectedPaths = utility::splitToVector(m_filesDialog->getText(), "\n");
|
||||||
|
closedFilesDialog();
|
||||||
|
|
||||||
|
std::vector<std::string> headerSearchPaths = m_list->getStringList();
|
||||||
|
|
||||||
|
headerSearchPaths.reserve(headerSearchPaths.size() + detectedPaths.size());
|
||||||
|
for (const std::string& detectedPath : detectedPaths)
|
||||||
|
{
|
||||||
|
if (!detectedPath.empty())
|
||||||
|
{
|
||||||
|
headerSearchPaths.push_back(detectedPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_list->setStringList(headerSearchPaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtProjectWizzardContentPathsHeaderSearch::closedPathsDialog()
|
||||||
|
{
|
||||||
|
m_pathsDialog->hide();
|
||||||
|
m_pathsDialog.reset();
|
||||||
|
|
||||||
|
window()->raise();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QtProjectWizzardContentPathsHeaderSearch::showDetectedIncludesResult(const std::set<FilePath>& detectedHeaderSearchPaths)
|
||||||
|
{
|
||||||
|
const std::set<FilePath> headerSearchPaths = utility::toSet(m_settings->makePathsExpandedAndAbsolute(m_list->getList()));
|
||||||
|
|
||||||
|
std::vector<FilePath> additionalHeaderSearchPaths;
|
||||||
|
for (const FilePath& detectedHeaderSearchPath : detectedHeaderSearchPaths)
|
||||||
|
{
|
||||||
|
if (headerSearchPaths.find(detectedHeaderSearchPath) == headerSearchPaths.end())
|
||||||
|
{
|
||||||
|
additionalHeaderSearchPaths.push_back(detectedHeaderSearchPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (additionalHeaderSearchPaths.empty())
|
||||||
|
{
|
||||||
|
QMessageBox msgBox;
|
||||||
|
msgBox.setText("<p>No additional include paths have been detected while searching the provided paths.</p>");
|
||||||
|
msgBox.exec();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string detailedText = "";
|
||||||
|
FilePath relativeRoot = m_list->getRelativeRootDirectory();
|
||||||
|
for (const FilePath& path : additionalHeaderSearchPaths)
|
||||||
|
{
|
||||||
|
if (!relativeRoot.empty())
|
||||||
|
{
|
||||||
|
const FilePath relPath = path.getRelativeTo(relativeRoot);
|
||||||
|
if (relPath.str().size() < path.str().size())
|
||||||
|
{
|
||||||
|
detailedText += relPath.str() + "\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
detailedText += path.str() + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_filesDialog = std::make_shared<QtTextEditDialog>(
|
||||||
|
"Detected Include Paths",
|
||||||
|
(
|
||||||
|
"<p>The following <b>" + std::to_string(additionalHeaderSearchPaths.size()) + "</b> include paths have been "
|
||||||
|
"detected and will be added to the include paths that are already defined by this Source Group.<b>"
|
||||||
|
).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
m_filesDialog->setup();
|
||||||
|
m_filesDialog->setCloseVisible(true);
|
||||||
|
m_filesDialog->updateNextButton("Finish");
|
||||||
|
|
||||||
|
m_filesDialog->setReadOnly(true);
|
||||||
|
m_filesDialog->setText(detailedText);
|
||||||
|
m_filesDialog->showWindow();
|
||||||
|
|
||||||
|
connect(m_filesDialog.get(), &QtTextEditDialog::finished, this, &QtProjectWizzardContentPathsHeaderSearch::finishedAcceptDetectedIncludePathsDialog);
|
||||||
|
connect(m_filesDialog.get(), &QtTextEditDialog::canceled, this, &QtProjectWizzardContentPathsHeaderSearch::closedFilesDialog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QtProjectWizzardContentPathsHeaderSearch::showValidationResult(const std::vector<IncludeDirective>& unresolvedIncludes)
|
void QtProjectWizzardContentPathsHeaderSearch::showValidationResult(const std::vector<IncludeDirective>& unresolvedIncludes)
|
||||||
{
|
{
|
||||||
if (unresolvedIncludes.empty())
|
if (unresolvedIncludes.empty())
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#ifndef QT_PROJECT_WIZZARD_CONTENT_PATHS_H
|
#ifndef QT_PROJECT_WIZZARD_CONTENT_PATHS_H
|
||||||
#define QT_PROJECT_WIZZARD_CONTENT_PATHS_H
|
#define QT_PROJECT_WIZZARD_CONTENT_PATHS_H
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "qt/window/project_wizzard/QtProjectWizzardContent.h"
|
#include "qt/window/project_wizzard/QtProjectWizzardContent.h"
|
||||||
#include "utility/path_detector/CombinedPathDetector.h"
|
#include "utility/path_detector/CombinedPathDetector.h"
|
||||||
|
|
||||||
@@ -9,6 +11,7 @@ class QCheckBox;
|
|||||||
class QComboBox;
|
class QComboBox;
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
class QtDirectoryListBox;
|
class QtDirectoryListBox;
|
||||||
|
class QtPathListDialog;
|
||||||
class SourceGroupSettings;
|
class SourceGroupSettings;
|
||||||
class SourceGroupSettingsCxxCdb;
|
class SourceGroupSettingsCxxCdb;
|
||||||
|
|
||||||
@@ -119,12 +122,19 @@ public:
|
|||||||
virtual bool isScrollAble() const override;
|
virtual bool isScrollAble() const override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void validateButtonClicked();
|
void detectIncludesButtonClicked();
|
||||||
|
void validateIncludesButtonClicked();
|
||||||
|
void finishedSelectDetectIncludesRootPathsDialog();
|
||||||
|
void finishedAcceptDetectedIncludePathsDialog();
|
||||||
|
void closedPathsDialog();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void showDetectedIncludesResult(const std::set<FilePath>& detectedHeaderSearchPaths);
|
||||||
void showValidationResult(const std::vector<IncludeDirective>& unresolvedIncludes);
|
void showValidationResult(const std::vector<IncludeDirective>& unresolvedIncludes);
|
||||||
|
QtThreadedFunctor<std::set<FilePath>> m_showDetectedIncludesResultFunctor;
|
||||||
QtThreadedFunctor<std::vector<IncludeDirective>> m_showValidationResultFunctor;
|
QtThreadedFunctor<std::vector<IncludeDirective>> m_showValidationResultFunctor;
|
||||||
|
|
||||||
|
std::shared_ptr<QtPathListDialog> m_pathsDialog;
|
||||||
const bool m_isCdb;
|
const bool m_isCdb;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ add_files(
|
|||||||
|
|
||||||
CommandlineTestSuite.h
|
CommandlineTestSuite.h
|
||||||
ConfigManagerTestSuite.h
|
ConfigManagerTestSuite.h
|
||||||
|
CxxIncludeProcessingTestSuite.h
|
||||||
CxxIndexSampleProjectsTestSuite.h
|
CxxIndexSampleProjectsTestSuite.h
|
||||||
CxxParserTestSuite.h
|
CxxParserTestSuite.h
|
||||||
CxxTypeNameTestSuite.h
|
CxxTypeNameTestSuite.h
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
#include "cxxtest/TestSuite.h"
|
||||||
|
|
||||||
|
#include "utility/text/TextAccess.h"
|
||||||
|
#include "utility/IncludeDirective.h"
|
||||||
|
#include "utility/IncludeProcessing.h"
|
||||||
|
|
||||||
|
class CxxIncludeProcessingTestSuite: public CxxTest::TestSuite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void test_include_detection_finds_include_with_quotes()
|
||||||
|
{
|
||||||
|
std::vector<IncludeDirective> includeDirectives = IncludeProcessing::getIncludeDirectives(TextAccess::createFromString(
|
||||||
|
"#include \"foo.h\"",
|
||||||
|
FilePath("foo.cpp")
|
||||||
|
));
|
||||||
|
|
||||||
|
TS_ASSERT(!includeDirectives.empty());
|
||||||
|
|
||||||
|
if (!includeDirectives.empty())
|
||||||
|
{
|
||||||
|
TS_ASSERT_EQUALS("foo.h", includeDirectives.front().getIncludedFile().str());
|
||||||
|
TS_ASSERT_EQUALS("foo.cpp", includeDirectives.front().getIncludingFile().str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_include_detection_finds_include_with_angle_brackets()
|
||||||
|
{
|
||||||
|
std::vector<IncludeDirective> includeDirectives = IncludeProcessing::getIncludeDirectives(TextAccess::createFromString(
|
||||||
|
"#include <foo.h>",
|
||||||
|
FilePath("foo.cpp")
|
||||||
|
));
|
||||||
|
|
||||||
|
TS_ASSERT(!includeDirectives.empty());
|
||||||
|
|
||||||
|
if (!includeDirectives.empty())
|
||||||
|
{
|
||||||
|
TS_ASSERT_EQUALS("foo.h", includeDirectives.front().getIncludedFile().str());
|
||||||
|
TS_ASSERT_EQUALS("foo.cpp", includeDirectives.front().getIncludingFile().str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void test_include_detection_finds_include_with_quotes_and_space_before_keyword()
|
||||||
|
{
|
||||||
|
std::vector<IncludeDirective> includeDirectives = IncludeProcessing::getIncludeDirectives(TextAccess::createFromString(
|
||||||
|
"# include \"foo.h\"",
|
||||||
|
FilePath("foo.cpp")
|
||||||
|
));
|
||||||
|
|
||||||
|
TS_ASSERT(!includeDirectives.empty());
|
||||||
|
|
||||||
|
if (!includeDirectives.empty())
|
||||||
|
{
|
||||||
|
TS_ASSERT_EQUALS("foo.h", includeDirectives.front().getIncludedFile().str());
|
||||||
|
TS_ASSERT_EQUALS("foo.cpp", includeDirectives.front().getIncludingFile().str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_include_detection_does_not_find_include_in_empty_file()
|
||||||
|
{
|
||||||
|
TS_ASSERT(IncludeProcessing::getIncludeDirectives(TextAccess::createFromString("")).empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_include_detection_does_not_find_include_in_file_without_preprocessor_directive()
|
||||||
|
{
|
||||||
|
TS_ASSERT(IncludeProcessing::getIncludeDirectives(TextAccess::createFromString("foo")).empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_include_detection_does_not_find_include_in_file_without_include_preprocessor_directive()
|
||||||
|
{
|
||||||
|
TS_ASSERT(IncludeProcessing::getIncludeDirectives(TextAccess::createFromString("#ifdef xx\n#endif")).empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_header_search_path_detection_does_not_find_path_relative_to_including_file()
|
||||||
|
{
|
||||||
|
std::set<FilePath> headerSearchDirectoies = IncludeProcessing::getHeaderSearchDirectories(
|
||||||
|
{ FilePath("data/CxxIncludeProcessingTestSuite/test_header_search_path_detection_does_not_find_path_relative_to_including_file/a.cpp") },
|
||||||
|
{ FilePath("data/CxxIncludeProcessingTestSuite/test_header_search_path_detection_does_not_find_path_relative_to_including_file") },
|
||||||
|
1, [&](float) {}
|
||||||
|
);
|
||||||
|
|
||||||
|
TS_ASSERT(headerSearchDirectoies.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_header_search_path_detection_finds_path_inside_sub_directory()
|
||||||
|
{
|
||||||
|
std::set<FilePath> headerSearchDirectoies = IncludeProcessing::getHeaderSearchDirectories(
|
||||||
|
{ FilePath("data/CxxIncludeProcessingTestSuite/test_header_search_path_detection_finds_path_inside_sub_directory/a.cpp") },
|
||||||
|
{ FilePath("data/CxxIncludeProcessingTestSuite/test_header_search_path_detection_finds_path_inside_sub_directory") },
|
||||||
|
1, [&](float) {}
|
||||||
|
);
|
||||||
|
|
||||||
|
TS_ASSERT(!headerSearchDirectoies.empty());
|
||||||
|
if (!headerSearchDirectoies.empty())
|
||||||
|
{
|
||||||
|
TS_ASSERT_EQUALS(
|
||||||
|
"CxxIncludeProcessingTestSuite/test_header_search_path_detection_finds_path_inside_sub_directory/include",
|
||||||
|
headerSearchDirectoies.begin()->getRelativeTo(FilePath("data").getAbsolute()).str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_header_search_path_detection_finds_path_relative_to_sub_directory()
|
||||||
|
{
|
||||||
|
std::set<FilePath> headerSearchDirectoies = IncludeProcessing::getHeaderSearchDirectories(
|
||||||
|
{ FilePath("data/CxxIncludeProcessingTestSuite/test_header_search_path_detection_finds_path_relative_to_sub_directory/a.cpp") },
|
||||||
|
{ FilePath("data/CxxIncludeProcessingTestSuite/test_header_search_path_detection_finds_path_relative_to_sub_directory") },
|
||||||
|
1, [&](float) {}
|
||||||
|
);
|
||||||
|
|
||||||
|
TS_ASSERT(!headerSearchDirectoies.empty());
|
||||||
|
if (!headerSearchDirectoies.empty())
|
||||||
|
{
|
||||||
|
TS_ASSERT_EQUALS(
|
||||||
|
"CxxIncludeProcessingTestSuite/test_header_search_path_detection_finds_path_relative_to_sub_directory/include",
|
||||||
|
headerSearchDirectoies.begin()->getRelativeTo(FilePath("data").getAbsolute()).str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -74,6 +74,13 @@ public:
|
|||||||
TS_ASSERT(path.getParentDirectory().empty());
|
TS_ASSERT(path.getParentDirectory().empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_file_path_without_parent_has_empty_parent_directory()
|
||||||
|
{
|
||||||
|
const FilePath path("a.cpp");
|
||||||
|
|
||||||
|
TS_ASSERT(path.getParentDirectory().empty());
|
||||||
|
}
|
||||||
|
|
||||||
void test_file_path_is_absolute()
|
void test_file_path_is_absolute()
|
||||||
{
|
{
|
||||||
const FilePath path("data/FilePathTestSuite/a.cpp");
|
const FilePath path("data/FilePathTestSuite/a.cpp");
|
||||||
|
|||||||
Reference in New Issue
Block a user