forked from qt-creator/qt-creator
CppTools: Classify ambiguous headers depending on other files
This applies for all project managers, except qmake. The qmake project
manager will make use of this in follow up changes.
Before, "foo.h" was always recognized as a CXXHeader. Now, it depends on
the other files. E.g. in a file list {"foo.h", "foo.c"} foo.h is now a
CHeader. In {"foo.h", "foo.c", "bar.cpp"} the file "foo.h" is ambiguous
and we will create two project parts, one where it is a CHeader, the
other where it is a CXXHeader.
Change-Id: I50505163368742584b1380c284d42cbe07cb4fc9
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -166,6 +166,7 @@ QString Utils::toString(ProjectFile::Kind kind)
|
||||
CASE_PROFECTFILEKIND(ObjCXXSource);
|
||||
CASE_PROFECTFILEKIND(CudaSource);
|
||||
CASE_PROFECTFILEKIND(OpenCLSource);
|
||||
CASE_PROFECTFILEKIND(AmbiguousHeader);
|
||||
// no default to get a compiler warning if anything is added
|
||||
}
|
||||
#undef CASE_PROFECTFILEKIND
|
||||
|
||||
@@ -41,6 +41,9 @@ ProjectFile::ProjectFile(const QString &filePath, Kind kind)
|
||||
|
||||
ProjectFile::Kind ProjectFile::classify(const QString &filePath)
|
||||
{
|
||||
if (isAmbiguousHeader(filePath))
|
||||
return AmbiguousHeader;
|
||||
|
||||
Utils::MimeDatabase mdb;
|
||||
const Utils::MimeType mimeType = mdb.mimeTypeForFile(filePath);
|
||||
if (!mimeType.isValid())
|
||||
@@ -65,6 +68,11 @@ ProjectFile::Kind ProjectFile::classify(const QString &filePath)
|
||||
return Unclassified;
|
||||
}
|
||||
|
||||
bool ProjectFile::isAmbiguousHeader(const QString &filePath)
|
||||
{
|
||||
return filePath.endsWith(".h");
|
||||
}
|
||||
|
||||
bool ProjectFile::isHeader(ProjectFile::Kind kind)
|
||||
{
|
||||
switch (kind) {
|
||||
@@ -73,6 +81,7 @@ bool ProjectFile::isHeader(ProjectFile::Kind kind)
|
||||
case ProjectFile::ObjCHeader:
|
||||
case ProjectFile::ObjCXXHeader:
|
||||
case ProjectFile::Unclassified: // no file extension, e.g. stl headers
|
||||
case ProjectFile::AmbiguousHeader:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -99,6 +108,7 @@ static const char *projectFileKindToText(ProjectFile::Kind kind)
|
||||
{
|
||||
switch (kind) {
|
||||
RETURN_TEXT_FOR_CASE(Unclassified);
|
||||
RETURN_TEXT_FOR_CASE(AmbiguousHeader);
|
||||
RETURN_TEXT_FOR_CASE(CHeader);
|
||||
RETURN_TEXT_FOR_CASE(CSource);
|
||||
RETURN_TEXT_FOR_CASE(CXXHeader);
|
||||
|
||||
@@ -36,6 +36,7 @@ class CPPTOOLS_EXPORT ProjectFile
|
||||
public:
|
||||
enum Kind {
|
||||
Unclassified,
|
||||
AmbiguousHeader,
|
||||
CHeader,
|
||||
CSource,
|
||||
CXXHeader,
|
||||
@@ -49,8 +50,10 @@ public:
|
||||
};
|
||||
|
||||
static Kind classify(const QString &filePath);
|
||||
static bool isHeader(Kind kind);
|
||||
|
||||
static bool isSource(Kind kind);
|
||||
static bool isHeader(Kind kind);
|
||||
static bool isAmbiguousHeader(const QString &filePath);
|
||||
|
||||
public:
|
||||
ProjectFile() = default;
|
||||
|
||||
@@ -32,42 +32,8 @@ ProjectFileCategorizer::ProjectFileCategorizer(const QString &projectPartName,
|
||||
ProjectPartBuilder::FileClassifier fileClassifier)
|
||||
: m_partName(projectPartName)
|
||||
{
|
||||
ProjectFiles cHeaders;
|
||||
ProjectFiles cxxHeaders;
|
||||
|
||||
foreach (const QString &filePath, filePaths) {
|
||||
const ProjectFile::Kind kind = fileClassifier
|
||||
? fileClassifier(filePath)
|
||||
: ProjectFile::classify(filePath);
|
||||
const ProjectFile projectFile(filePath, kind);
|
||||
|
||||
switch (kind) {
|
||||
case ProjectFile::CSource: m_cSources += projectFile; break;
|
||||
case ProjectFile::CHeader: cHeaders += projectFile; break;
|
||||
case ProjectFile::CXXSource: m_cxxSources += projectFile; break;
|
||||
case ProjectFile::CXXHeader: cxxHeaders += projectFile; break;
|
||||
case ProjectFile::ObjCSource: m_objcSources += projectFile; break;
|
||||
case ProjectFile::ObjCXXSource: m_objcxxSources += projectFile; break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const bool hasC = !m_cSources.isEmpty();
|
||||
const bool hasCxx = !m_cxxSources.isEmpty();
|
||||
const bool hasObjc = !m_objcSources.isEmpty();
|
||||
const bool hasObjcxx = !m_objcxxSources.isEmpty();
|
||||
|
||||
if (hasObjcxx)
|
||||
m_objcxxSources += cxxHeaders + cHeaders;
|
||||
if (hasCxx)
|
||||
m_cxxSources += cxxHeaders + cHeaders;
|
||||
else if (!hasObjcxx)
|
||||
m_cxxSources += cxxHeaders;
|
||||
if (hasObjc)
|
||||
m_objcSources += cHeaders;
|
||||
if (hasC || (!hasObjc && !hasObjcxx && !hasCxx))
|
||||
m_cSources += cHeaders;
|
||||
const QStringList ambiguousHeaders = classifyFiles(filePaths, fileClassifier);
|
||||
expandSourcesWithAmbiguousHeaders(ambiguousHeaders);
|
||||
|
||||
m_partCount = (m_cSources.isEmpty() ? 0 : 1)
|
||||
+ (m_cxxSources.isEmpty() ? 0 : 1)
|
||||
@@ -83,4 +49,81 @@ QString ProjectFileCategorizer::partName(const QString &languageName) const
|
||||
return m_partName;
|
||||
}
|
||||
|
||||
QStringList ProjectFileCategorizer::classifyFiles(
|
||||
const QStringList &filePaths,
|
||||
ProjectPartBuilder::FileClassifier fileClassifier)
|
||||
{
|
||||
QStringList ambiguousHeaders;
|
||||
|
||||
foreach (const QString &filePath, filePaths) {
|
||||
const ProjectFile::Kind kind = fileClassifier
|
||||
? fileClassifier(filePath)
|
||||
: ProjectFile::classify(filePath);
|
||||
|
||||
switch (kind) {
|
||||
case ProjectFile::AmbiguousHeader:
|
||||
ambiguousHeaders += filePath;
|
||||
break;
|
||||
case ProjectFile::CXXSource:
|
||||
case ProjectFile::CXXHeader:
|
||||
m_cxxSources += ProjectFile(filePath, kind);
|
||||
break;
|
||||
case ProjectFile::ObjCXXSource:
|
||||
case ProjectFile::ObjCXXHeader:
|
||||
m_objcxxSources += ProjectFile(filePath, kind);
|
||||
break;
|
||||
case ProjectFile::CSource:
|
||||
case ProjectFile::CHeader:
|
||||
m_cSources += ProjectFile(filePath, kind);
|
||||
break;
|
||||
case ProjectFile::ObjCSource:
|
||||
case ProjectFile::ObjCHeader:
|
||||
m_objcSources += ProjectFile(filePath, kind);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return ambiguousHeaders;
|
||||
}
|
||||
|
||||
static ProjectFiles toProjectFilesWithKind(const QStringList &filePaths,
|
||||
const ProjectFile::Kind kind)
|
||||
{
|
||||
ProjectFiles projectFiles;
|
||||
projectFiles.reserve(filePaths.size());
|
||||
|
||||
foreach (const QString &filePath, filePaths)
|
||||
projectFiles += ProjectFile(filePath, kind);
|
||||
|
||||
return projectFiles;
|
||||
}
|
||||
|
||||
void ProjectFileCategorizer::expandSourcesWithAmbiguousHeaders(const QStringList &ambiguousHeaders)
|
||||
{
|
||||
const bool hasC = !m_cSources.isEmpty();
|
||||
const bool hasCxx = !m_cxxSources.isEmpty();
|
||||
const bool hasObjc = !m_objcSources.isEmpty();
|
||||
const bool hasObjcxx = !m_objcxxSources.isEmpty();
|
||||
const bool hasOnlyAmbiguousHeaders
|
||||
= !hasC
|
||||
&& !hasCxx
|
||||
&& !hasObjc
|
||||
&& !hasObjcxx
|
||||
&& !ambiguousHeaders.isEmpty();
|
||||
|
||||
if (hasC || hasOnlyAmbiguousHeaders)
|
||||
m_cSources += toProjectFilesWithKind(ambiguousHeaders, ProjectFile::CHeader);
|
||||
|
||||
if (hasCxx || hasOnlyAmbiguousHeaders)
|
||||
m_cxxSources += toProjectFilesWithKind(ambiguousHeaders, ProjectFile::CXXHeader);
|
||||
|
||||
if (hasObjc || hasOnlyAmbiguousHeaders)
|
||||
m_objcSources += toProjectFilesWithKind(ambiguousHeaders, ProjectFile::ObjCHeader);
|
||||
|
||||
if (hasObjcxx || hasOnlyAmbiguousHeaders)
|
||||
m_objcxxSources += toProjectFilesWithKind(ambiguousHeaders, ProjectFile::ObjCXXHeader);
|
||||
}
|
||||
|
||||
} // namespace CppTools
|
||||
|
||||
@@ -35,11 +35,13 @@ namespace CppTools {
|
||||
|
||||
class ProjectFileCategorizer
|
||||
{
|
||||
public:
|
||||
using FileClassifier = ProjectPartBuilder::FileClassifier;
|
||||
|
||||
public:
|
||||
ProjectFileCategorizer(const QString &projectPartName,
|
||||
const QStringList &filePaths,
|
||||
ProjectPartBuilder::FileClassifier fileClassifier
|
||||
= ProjectPartBuilder::FileClassifier());
|
||||
FileClassifier fileClassifier = FileClassifier());
|
||||
|
||||
bool hasCSources() const { return !m_cSources.isEmpty(); }
|
||||
bool hasCxxSources() const { return !m_cxxSources.isEmpty(); }
|
||||
@@ -56,6 +58,10 @@ public:
|
||||
|
||||
QString partName(const QString &languageName) const;
|
||||
|
||||
private:
|
||||
QStringList classifyFiles(const QStringList &filePaths, FileClassifier fileClassifier);
|
||||
void expandSourcesWithAmbiguousHeaders(const QStringList &ambiguousHeaders);
|
||||
|
||||
private:
|
||||
QString m_partName;
|
||||
ProjectFiles m_cSources;
|
||||
|
||||
@@ -279,7 +279,7 @@ static QStringList matchingCandidateSuffixes(ProjectFile::Kind kind)
|
||||
{
|
||||
Utils::MimeDatabase mdb;
|
||||
switch (kind) {
|
||||
// Note that C/C++ headers are undistinguishable
|
||||
case ProjectFile::AmbiguousHeader:
|
||||
case ProjectFile::CHeader:
|
||||
case ProjectFile::CXXHeader:
|
||||
case ProjectFile::ObjCHeader:
|
||||
|
||||
@@ -8,10 +8,12 @@ HEADERS += \
|
||||
$$PWD/cppprojectfile.h \
|
||||
$$PWD/senddocumenttracker.h \
|
||||
$$PWD/projectpart.h \
|
||||
$$PWD/compileroptionsbuilder.h
|
||||
$$PWD/compileroptionsbuilder.h \
|
||||
$$PWD/cppprojectfilecategorizer.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/cppprojectfile.cpp \
|
||||
$$PWD/senddocumenttracker.cpp \
|
||||
$$PWD/projectpart.cpp \
|
||||
$$PWD/compileroptionsbuilder.cpp
|
||||
$$PWD/compileroptionsbuilder.cpp \
|
||||
$$PWD/cppprojectfilecategorizer.cpp
|
||||
|
||||
Reference in New Issue
Block a user