forked from qt-creator/qt-creator
CompilationDatabase: Support both code models
Extract headers, defines and fileKind from flags in order to have complete project parts. Side-effect: better support for MSVC-specific flags. Change-Id: Iaa1413c91c96c3cf89ddbe76a7a1f0f46c5289c0 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
@@ -26,133 +26,48 @@
|
|||||||
#include "compilationdatabaseproject.h"
|
#include "compilationdatabaseproject.h"
|
||||||
|
|
||||||
#include "compilationdatabaseconstants.h"
|
#include "compilationdatabaseconstants.h"
|
||||||
|
#include "compilationdatabaseutils.h"
|
||||||
|
|
||||||
#include <coreplugin/icontext.h>
|
#include <coreplugin/icontext.h>
|
||||||
#include <cpptools/projectinfo.h>
|
#include <cpptools/projectinfo.h>
|
||||||
#include <cpptools/cppprojectupdater.h>
|
#include <cpptools/cppprojectupdater.h>
|
||||||
#include <projectexplorer/gcctoolchain.h>
|
#include <projectexplorer/gcctoolchain.h>
|
||||||
|
#include <projectexplorer/headerpath.h>
|
||||||
#include <projectexplorer/kitinformation.h>
|
#include <projectexplorer/kitinformation.h>
|
||||||
#include <projectexplorer/kitmanager.h>
|
#include <projectexplorer/kitmanager.h>
|
||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
#include <projectexplorer/projectnodes.h>
|
#include <projectexplorer/projectnodes.h>
|
||||||
#include <projectexplorer/target.h>
|
|
||||||
#include <projectexplorer/toolchainconfigwidget.h>
|
#include <projectexplorer/toolchainconfigwidget.h>
|
||||||
|
#include <projectexplorer/toolchainmanager.h>
|
||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
|
|
||||||
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
#include <utils/runextensions.h>
|
#include <utils/runextensions.h>
|
||||||
|
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
|
||||||
#include <QRegularExpression>
|
#ifdef Q_OS_WIN
|
||||||
|
#include <Windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
namespace CompilationDatabaseProjectManager {
|
namespace CompilationDatabaseProjectManager {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class DBProjectNode : public ProjectExplorer::ProjectNode
|
namespace {
|
||||||
|
class DBProjectNode : public ProjectNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit DBProjectNode(const Utils::FileName &projectFilePath)
|
explicit DBProjectNode(const Utils::FileName &projectFilePath)
|
||||||
: ProjectExplorer::ProjectNode(projectFilePath)
|
: ProjectNode(projectFilePath)
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
static QStringList splitCommandLine(QString commandLine)
|
QStringList jsonObjectFlags(const QJsonObject &object)
|
||||||
{
|
|
||||||
QStringList result;
|
|
||||||
bool insideQuotes = false;
|
|
||||||
|
|
||||||
// Remove escaped quotes.
|
|
||||||
commandLine.replace("\\\"", "'");
|
|
||||||
for (const QString &part : commandLine.split(QRegularExpression("\""))) {
|
|
||||||
if (insideQuotes) {
|
|
||||||
const QString quotedPart = "\"" + part + "\"";
|
|
||||||
if (result.last().endsWith("="))
|
|
||||||
result.last().append(quotedPart);
|
|
||||||
else
|
|
||||||
result.append(quotedPart);
|
|
||||||
} else { // If 's' is outside quotes ...
|
|
||||||
result.append(part.split(QRegularExpression("\\s+"), QString::SkipEmptyParts));
|
|
||||||
}
|
|
||||||
insideQuotes = !insideQuotes;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString updatedPathFlag(const QString &pathStr, const QString &workingDir,
|
|
||||||
const QString &originalFlag)
|
|
||||||
{
|
|
||||||
QString result = pathStr;
|
|
||||||
if (!QDir(pathStr).exists()
|
|
||||||
&& QDir(workingDir + "/" + pathStr).exists()) {
|
|
||||||
result = workingDir + "/" + pathStr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (originalFlag.startsWith("-I"))
|
|
||||||
return "-I" + result;
|
|
||||||
|
|
||||||
if (originalFlag.startsWith("-isystem"))
|
|
||||||
return "-isystem" + result;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QStringList filteredFlags(const QStringList &flags, const QString &fileName,
|
|
||||||
const QString &workingDir)
|
|
||||||
{
|
|
||||||
QStringList filtered;
|
|
||||||
// Skip compiler call if present.
|
|
||||||
bool skipNext = !flags.first().startsWith('-');
|
|
||||||
bool includePath = false;
|
|
||||||
|
|
||||||
for (const QString &flag : flags) {
|
|
||||||
if (skipNext) {
|
|
||||||
skipNext = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString pathStr;
|
|
||||||
if (includePath) {
|
|
||||||
includePath = false;
|
|
||||||
pathStr = flag;
|
|
||||||
} else if ((flag.startsWith("-I") || flag.startsWith("-isystem"))
|
|
||||||
&& flag != "-I" && flag != "-isystem") {
|
|
||||||
pathStr = flag.mid(flag.startsWith("-I") ? 2 : 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pathStr.isEmpty()) {
|
|
||||||
filtered.push_back(updatedPathFlag(pathStr, workingDir, flag));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flag == "-c" || flag == "-pedantic" || flag.startsWith("/") || flag.startsWith("-m")
|
|
||||||
|| flag.startsWith("-O") || flag.startsWith("-W") || flag.startsWith("-w")
|
|
||||||
|| flag.startsWith("--sysroot=")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flag == "-target" || flag == "-triple" || flag == "-isysroot" || flag == "-isystem"
|
|
||||||
|| flag == "--sysroot") {
|
|
||||||
skipNext = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flag.endsWith(fileName))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (flag == "-I" || flag == "-isystem")
|
|
||||||
includePath = true;
|
|
||||||
|
|
||||||
filtered.push_back(flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
return filtered;
|
|
||||||
}
|
|
||||||
|
|
||||||
static CppTools::RawProjectPart makeRawProjectPart(const Utils::FileName &projectFile,
|
|
||||||
const QJsonObject &object,
|
|
||||||
const QString &workingDir,
|
|
||||||
const Utils::FileName &fileName)
|
|
||||||
{
|
{
|
||||||
QStringList flags;
|
QStringList flags;
|
||||||
const QJsonArray arguments = object["arguments"].toArray();
|
const QJsonArray arguments = object["arguments"].toArray();
|
||||||
@@ -163,21 +78,234 @@ static CppTools::RawProjectPart makeRawProjectPart(const Utils::FileName &projec
|
|||||||
flags.append(arg.toString());
|
flags.append(arg.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = filteredFlags(flags, fileName.fileName(), workingDir);
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isGccCompiler(const QString &compilerName)
|
||||||
|
{
|
||||||
|
return compilerName.contains("gcc") || compilerName.contains("g++");
|
||||||
|
}
|
||||||
|
|
||||||
|
Core::Id getCompilerId(QString compilerName)
|
||||||
|
{
|
||||||
|
if (Utils::HostOsInfo::isWindowsHost()) {
|
||||||
|
if (compilerName.endsWith(".exe"))
|
||||||
|
compilerName.chop(4);
|
||||||
|
if (isGccCompiler(compilerName))
|
||||||
|
return ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID;
|
||||||
|
|
||||||
|
// Default is clang-cl
|
||||||
|
return ProjectExplorer::Constants::CLANG_CL_TOOLCHAIN_TYPEID;
|
||||||
|
}
|
||||||
|
if (isGccCompiler(compilerName))
|
||||||
|
return ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID;
|
||||||
|
|
||||||
|
// Default is clang
|
||||||
|
return ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID;
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolChain *toolchainFromCompilerId(const Core::Id &compilerId, const Core::Id &language)
|
||||||
|
{
|
||||||
|
return ToolChainManager::toolChain([&compilerId, &language](const ToolChain *tc) {
|
||||||
|
if (!tc->isValid() || tc->language() != language)
|
||||||
|
return false;
|
||||||
|
return tc->typeId() == compilerId;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QString compilerPath(QString pathFlag)
|
||||||
|
{
|
||||||
|
if (pathFlag.isEmpty())
|
||||||
|
return pathFlag;
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
// Handle short DOS style file names (cmake can generate them).
|
||||||
|
const DWORD pathLength = GetLongPathNameW((LPCWSTR)pathFlag.utf16(), 0, 0);
|
||||||
|
wchar_t* buffer = new wchar_t[pathLength];
|
||||||
|
GetLongPathNameW((LPCWSTR)pathFlag.utf16(), buffer, pathLength);
|
||||||
|
pathFlag = QString::fromUtf16((ushort *)buffer, pathLength - 1);
|
||||||
|
delete[] buffer;
|
||||||
|
#endif
|
||||||
|
return QDir::fromNativeSeparators(pathFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
ToolChain *toolchainFromFlags(const Kit *kit, const QStringList &flags, const Core::Id &language)
|
||||||
|
{
|
||||||
|
if (flags.empty())
|
||||||
|
return ToolChainKitInformation::toolChain(kit, language);
|
||||||
|
|
||||||
|
// Try exact compiler match.
|
||||||
|
const Utils::FileName compiler = Utils::FileName::fromString(compilerPath(flags.front()));
|
||||||
|
ToolChain *toolchain = ToolChainManager::toolChain([&compiler, &language](const ToolChain *tc) {
|
||||||
|
return tc->isValid() && tc->language() == language && tc->compilerCommand() == compiler;
|
||||||
|
});
|
||||||
|
if (toolchain)
|
||||||
|
return toolchain;
|
||||||
|
|
||||||
|
Core::Id compilerId = getCompilerId(compiler.fileName());
|
||||||
|
if ((toolchain = toolchainFromCompilerId(compilerId, language)))
|
||||||
|
return toolchain;
|
||||||
|
|
||||||
|
if (compilerId != ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID &&
|
||||||
|
compilerId != ProjectExplorer::Constants::CLANG_CL_TOOLCHAIN_TYPEID) {
|
||||||
|
compilerId = Utils::HostOsInfo::isWindowsHost()
|
||||||
|
? ProjectExplorer::Constants::CLANG_CL_TOOLCHAIN_TYPEID
|
||||||
|
: ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID;
|
||||||
|
if ((toolchain = toolchainFromCompilerId(compilerId, language)))
|
||||||
|
return toolchain;
|
||||||
|
}
|
||||||
|
|
||||||
|
toolchain = ToolChainKitInformation::toolChain(kit, language);
|
||||||
|
qWarning() << QCoreApplication::translate("CompilationDatabaseProject",
|
||||||
|
"No matching toolchain found, use the default.");
|
||||||
|
return toolchain;
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::FileName jsonObjectFilename(const QJsonObject &object)
|
||||||
|
{
|
||||||
|
const QString workingDir = object["directory"].toString();
|
||||||
|
Utils::FileName fileName = Utils::FileName::fromString(
|
||||||
|
QDir::fromNativeSeparators(object["file"].toString()));
|
||||||
|
if (fileName.toFileInfo().isRelative()) {
|
||||||
|
fileName = Utils::FileUtils::canonicalPath(
|
||||||
|
Utils::FileName::fromString(workingDir + "/" + fileName.toString()));
|
||||||
|
}
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addDriverModeFlagIfNeeded(const ToolChain *toolchain, QStringList &flags)
|
||||||
|
{
|
||||||
|
if (toolchain->typeId() == ProjectExplorer::Constants::CLANG_CL_TOOLCHAIN_TYPEID
|
||||||
|
&& !flags.empty() && !flags.front().endsWith("cl")
|
||||||
|
&& !flags.front().endsWith("cl.exe")) {
|
||||||
|
flags.insert(1, "--driver-mode=g++");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CppTools::RawProjectPart makeRawProjectPart(const Utils::FileName &projectFile,
|
||||||
|
Kit *kit,
|
||||||
|
ToolChain *&cToolchain,
|
||||||
|
ToolChain *&cxxToolchain,
|
||||||
|
const QString &workingDir,
|
||||||
|
const Utils::FileName &fileName,
|
||||||
|
QStringList flags)
|
||||||
|
{
|
||||||
|
HeaderPaths headerPaths;
|
||||||
|
Macros macros;
|
||||||
|
CppTools::ProjectFile::Kind fileKind = CppTools::ProjectFile::Unclassified;
|
||||||
|
|
||||||
|
const QStringList originalFlags = flags;
|
||||||
|
filteredFlags(fileName.fileName(),
|
||||||
|
workingDir,
|
||||||
|
flags,
|
||||||
|
headerPaths,
|
||||||
|
macros,
|
||||||
|
fileKind);
|
||||||
|
|
||||||
CppTools::RawProjectPart rpp;
|
CppTools::RawProjectPart rpp;
|
||||||
rpp.setProjectFileLocation(projectFile.toString());
|
rpp.setProjectFileLocation(projectFile.toString());
|
||||||
rpp.setBuildSystemTarget(workingDir);
|
rpp.setBuildSystemTarget(workingDir);
|
||||||
rpp.setDisplayName(fileName.fileName());
|
rpp.setDisplayName(fileName.fileName());
|
||||||
rpp.setFiles({fileName.toString()});
|
rpp.setFiles({fileName.toString()});
|
||||||
|
rpp.setHeaderPaths(headerPaths);
|
||||||
|
rpp.setMacros(macros);
|
||||||
|
|
||||||
CppTools::RawProjectPartFlags cxxProjectFlags;
|
if (fileKind == CppTools::ProjectFile::Kind::CHeader
|
||||||
cxxProjectFlags.commandLineFlags = flags;
|
|| fileKind == CppTools::ProjectFile::Kind::CSource) {
|
||||||
rpp.setFlagsForCxx(cxxProjectFlags);
|
if (!cToolchain) {
|
||||||
|
cToolchain = toolchainFromFlags(kit, originalFlags,
|
||||||
|
ProjectExplorer::Constants::C_LANGUAGE_ID);
|
||||||
|
ToolChainKitInformation::setToolChain(kit, cToolchain);
|
||||||
|
}
|
||||||
|
addDriverModeFlagIfNeeded(cToolchain, flags);
|
||||||
|
rpp.setFlagsForC({cToolchain, flags});
|
||||||
|
} else {
|
||||||
|
if (!cxxToolchain) {
|
||||||
|
cxxToolchain = toolchainFromFlags(kit, originalFlags,
|
||||||
|
ProjectExplorer::Constants::CXX_LANGUAGE_ID);
|
||||||
|
ToolChainKitInformation::setToolChain(kit, cxxToolchain);
|
||||||
|
}
|
||||||
|
addDriverModeFlagIfNeeded(cxxToolchain, flags);
|
||||||
|
rpp.setFlagsForCxx({cxxToolchain, flags});
|
||||||
|
}
|
||||||
|
|
||||||
return rpp;
|
return rpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
void CompilationDatabaseProject::buildTreeAndProjectParts(const Utils::FileName &projectFile)
|
||||||
|
{
|
||||||
|
QFile file(projectFilePath().toString());
|
||||||
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
|
emitParsingFinished(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QJsonArray array = QJsonDocument::fromJson(file.readAll()).array();
|
||||||
|
|
||||||
|
auto root = std::make_unique<DBProjectNode>(projectDirectory());
|
||||||
|
root->addNode(std::make_unique<FileNode>(
|
||||||
|
projectFile,
|
||||||
|
FileType::Project,
|
||||||
|
false));
|
||||||
|
auto headers = std::make_unique<VirtualFolderNode>(
|
||||||
|
Utils::FileName::fromString("Headers"), 0);
|
||||||
|
auto sources = std::make_unique<VirtualFolderNode>(
|
||||||
|
Utils::FileName::fromString("Sources"), 0);
|
||||||
|
|
||||||
|
CppTools::RawProjectParts rpps;
|
||||||
|
ToolChain *cToolchain = nullptr;
|
||||||
|
ToolChain *cxxToolchain = nullptr;
|
||||||
|
for (const QJsonValue &element : array) {
|
||||||
|
const QJsonObject object = element.toObject();
|
||||||
|
|
||||||
|
Utils::FileName fileName = jsonObjectFilename(object);
|
||||||
|
const QStringList flags = jsonObjectFlags(object);
|
||||||
|
const QString filePath = fileName.toString();
|
||||||
|
|
||||||
|
const CppTools::ProjectFile::Kind kind = CppTools::ProjectFile::classify(filePath);
|
||||||
|
FolderNode *parent = nullptr;
|
||||||
|
FileType type = FileType::Unknown;
|
||||||
|
if (CppTools::ProjectFile::isHeader(kind)) {
|
||||||
|
parent = headers.get();
|
||||||
|
type = FileType::Header;
|
||||||
|
} else if (CppTools::ProjectFile::isSource(kind)) {
|
||||||
|
parent = sources.get();
|
||||||
|
type = FileType::Source;
|
||||||
|
} else {
|
||||||
|
parent = root.get();
|
||||||
|
}
|
||||||
|
parent->addNode(std::make_unique<FileNode>(fileName, type, false));
|
||||||
|
|
||||||
|
CppTools::RawProjectPart rpp = makeRawProjectPart(projectFile,
|
||||||
|
m_kit.get(),
|
||||||
|
cToolchain,
|
||||||
|
cxxToolchain,
|
||||||
|
object["directory"].toString(),
|
||||||
|
fileName,
|
||||||
|
flags);
|
||||||
|
int rppIndex = Utils::indexOf(rpps, [&rpp](const CppTools::RawProjectPart ¤tRpp) {
|
||||||
|
return rpp.buildSystemTarget == currentRpp.buildSystemTarget
|
||||||
|
&& rpp.headerPaths == currentRpp.headerPaths
|
||||||
|
&& rpp.projectMacros == currentRpp.projectMacros
|
||||||
|
&& rpp.flagsForCxx.commandLineFlags == currentRpp.flagsForCxx.commandLineFlags;
|
||||||
|
});
|
||||||
|
if (rppIndex == -1)
|
||||||
|
rpps.append(rpp);
|
||||||
|
else
|
||||||
|
rpps[rppIndex].files.append(rpp.files);
|
||||||
|
}
|
||||||
|
|
||||||
|
root->addNode(std::move(headers));
|
||||||
|
root->addNode(std::move(sources));
|
||||||
|
|
||||||
|
setRootProjectNode(std::move(root));
|
||||||
|
|
||||||
|
m_cppCodeModelUpdater->update({this, cToolchain, cxxToolchain, m_kit.get(), rpps});
|
||||||
|
|
||||||
|
emitParsingFinished(true);
|
||||||
|
}
|
||||||
|
|
||||||
CompilationDatabaseProject::CompilationDatabaseProject(const Utils::FileName &projectFile)
|
CompilationDatabaseProject::CompilationDatabaseProject(const Utils::FileName &projectFile)
|
||||||
: Project(Constants::COMPILATIONDATABASEMIMETYPE, projectFile)
|
: Project(Constants::COMPILATIONDATABASEMIMETYPE, projectFile)
|
||||||
, m_cppCodeModelUpdater(std::make_unique<CppTools::CppProjectUpdater>(this))
|
, m_cppCodeModelUpdater(std::make_unique<CppTools::CppProjectUpdater>(this))
|
||||||
@@ -185,90 +313,17 @@ CompilationDatabaseProject::CompilationDatabaseProject(const Utils::FileName &pr
|
|||||||
setId(Constants::COMPILATIONDATABASEPROJECT_ID);
|
setId(Constants::COMPILATIONDATABASEPROJECT_ID);
|
||||||
setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
|
setProjectLanguages(Core::Context(ProjectExplorer::Constants::CXX_LANGUAGE_ID));
|
||||||
setDisplayName(projectDirectory().fileName());
|
setDisplayName(projectDirectory().fileName());
|
||||||
|
setRequiredKitPredicate([](const Kit *) { return false; });
|
||||||
|
setPreferredKitPredicate([](const Kit *) { return false; });
|
||||||
|
|
||||||
connect(this, &Project::activeTargetChanged, [this, projectFile](ProjectExplorer::Target *target) {
|
m_kit.reset(KitManager::defaultKit()->clone());
|
||||||
if (!target)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ProjectExplorer::Kit *kit = target->kit();
|
emitParsingStarted();
|
||||||
if (!kit)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto toolchains = ProjectExplorer::ToolChainKitInformation::toolChains(kit);
|
const QFuture<void> future = ::Utils::runAsync([this, projectFile](){
|
||||||
if (toolchains.isEmpty())
|
buildTreeAndProjectParts(projectFile);
|
||||||
return;
|
|
||||||
|
|
||||||
emitParsingStarted();
|
|
||||||
|
|
||||||
const QFuture<void> future = ::Utils::runAsync([this, projectFile, kit,
|
|
||||||
tc = toolchains.first()](){
|
|
||||||
QFile file(projectFilePath().toString());
|
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
|
||||||
emitParsingFinished(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QJsonArray array = QJsonDocument::fromJson(file.readAll()).array();
|
|
||||||
|
|
||||||
auto root = std::make_unique<DBProjectNode>(projectDirectory());
|
|
||||||
root->addNode(std::make_unique<ProjectExplorer::FileNode>(
|
|
||||||
projectFile,
|
|
||||||
ProjectExplorer::FileType::Project,
|
|
||||||
false));
|
|
||||||
auto headers = std::make_unique<ProjectExplorer::VirtualFolderNode>(
|
|
||||||
Utils::FileName::fromString("Headers"), 0);
|
|
||||||
auto sources = std::make_unique<ProjectExplorer::VirtualFolderNode>(
|
|
||||||
Utils::FileName::fromString("Sources"), 0);
|
|
||||||
CppTools::RawProjectParts rpps;
|
|
||||||
for (const QJsonValue &element : array) {
|
|
||||||
const QJsonObject object = element.toObject();
|
|
||||||
const QString workingDir = object["directory"].toString();
|
|
||||||
Utils::FileName fileName = Utils::FileName::fromString(
|
|
||||||
QDir::fromNativeSeparators(object["file"].toString()));
|
|
||||||
if (!fileName.exists()) {
|
|
||||||
fileName = Utils::FileUtils::canonicalPath(
|
|
||||||
Utils::FileName::fromString(workingDir + "/" + fileName.toString()));
|
|
||||||
}
|
|
||||||
const QString filePath = fileName.toString();
|
|
||||||
const CppTools::ProjectFile::Kind kind = CppTools::ProjectFile::classify(filePath);
|
|
||||||
ProjectExplorer::FolderNode *parent = nullptr;
|
|
||||||
ProjectExplorer::FileType type = ProjectExplorer::FileType::Unknown;
|
|
||||||
if (CppTools::ProjectFile::isHeader(kind)) {
|
|
||||||
parent = headers.get();
|
|
||||||
type = ProjectExplorer::FileType::Header;
|
|
||||||
} else if (CppTools::ProjectFile::isSource(kind)) {
|
|
||||||
parent = sources.get();
|
|
||||||
type = ProjectExplorer::FileType::Source;
|
|
||||||
} else {
|
|
||||||
parent = root.get();
|
|
||||||
}
|
|
||||||
parent->addNode(std::make_unique<ProjectExplorer::FileNode>(
|
|
||||||
fileName, type, false));
|
|
||||||
|
|
||||||
rpps.append(makeRawProjectPart(projectFile, object, workingDir, fileName));
|
|
||||||
}
|
|
||||||
|
|
||||||
root->addNode(std::move(headers));
|
|
||||||
root->addNode(std::move(sources));
|
|
||||||
|
|
||||||
setRootProjectNode(std::move(root));
|
|
||||||
|
|
||||||
CppTools::ToolChainInfo tcInfo;
|
|
||||||
tcInfo.type = ProjectExplorer::Constants::COMPILATION_DATABASE_TOOLCHAIN_TYPEID;
|
|
||||||
tcInfo.isMsvc2015ToolChain
|
|
||||||
= tc->targetAbi().osFlavor() == ProjectExplorer::Abi::WindowsMsvc2015Flavor;
|
|
||||||
tcInfo.wordWidth = tc->targetAbi().wordWidth();
|
|
||||||
tcInfo.targetTriple = tc->originalTargetTriple();
|
|
||||||
tcInfo.sysRootPath = ProjectExplorer::SysRootKitInformation::sysRoot(kit).toString();
|
|
||||||
tcInfo.headerPathsRunner = tc->createBuiltInHeaderPathsRunner();
|
|
||||||
tcInfo.macroInspectionRunner = tc->createMacroInspectionRunner();
|
|
||||||
|
|
||||||
m_cppCodeModelUpdater->update({this, tcInfo, tcInfo, rpps});
|
|
||||||
|
|
||||||
emitParsingFinished(true);
|
|
||||||
});
|
|
||||||
m_parserWatcher.setFuture(future);
|
|
||||||
});
|
});
|
||||||
|
m_parserWatcher.setFuture(future);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompilationDatabaseProject::~CompilationDatabaseProject()
|
CompilationDatabaseProject::~CompilationDatabaseProject()
|
||||||
|
@@ -35,6 +35,8 @@ namespace CppTools {
|
|||||||
class CppProjectUpdater;
|
class CppProjectUpdater;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ProjectExplorer { class Kit; }
|
||||||
|
|
||||||
namespace CompilationDatabaseProjectManager {
|
namespace CompilationDatabaseProjectManager {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -45,10 +47,15 @@ class CompilationDatabaseProject : public ProjectExplorer::Project
|
|||||||
public:
|
public:
|
||||||
explicit CompilationDatabaseProject(const Utils::FileName &filename);
|
explicit CompilationDatabaseProject(const Utils::FileName &filename);
|
||||||
~CompilationDatabaseProject() override;
|
~CompilationDatabaseProject() override;
|
||||||
|
bool needsConfiguration() const override { return false; }
|
||||||
|
bool needsBuildConfigurations() const override { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void buildTreeAndProjectParts(const Utils::FileName &projectFile);
|
||||||
|
|
||||||
QFutureWatcher<void> m_parserWatcher;
|
QFutureWatcher<void> m_parserWatcher;
|
||||||
std::unique_ptr<CppTools::CppProjectUpdater> m_cppCodeModelUpdater;
|
std::unique_ptr<CppTools::CppProjectUpdater> m_cppCodeModelUpdater;
|
||||||
|
std::unique_ptr<ProjectExplorer::Kit> m_kit;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CompilationDatabaseEditorFactory : public TextEditor::TextEditorFactory
|
class CompilationDatabaseEditorFactory : public TextEditor::TextEditorFactory
|
||||||
|
@@ -2,9 +2,21 @@ include(../../qtcreatorplugin.pri)
|
|||||||
|
|
||||||
SOURCES = \
|
SOURCES = \
|
||||||
compilationdatabaseproject.cpp \
|
compilationdatabaseproject.cpp \
|
||||||
compilationdatabaseprojectmanagerplugin.cpp
|
compilationdatabaseprojectmanagerplugin.cpp \
|
||||||
|
compilationdatabaseutils.cpp
|
||||||
|
|
||||||
HEADERS = \
|
HEADERS = \
|
||||||
compilationdatabaseproject.h \
|
compilationdatabaseproject.h \
|
||||||
compilationdatabaseprojectmanagerplugin.h \
|
compilationdatabaseprojectmanagerplugin.h \
|
||||||
compilationdatabaseconstants.h
|
compilationdatabaseconstants.h \
|
||||||
|
compilationdatabaseutils.h
|
||||||
|
|
||||||
|
equals(TEST, 1) {
|
||||||
|
HEADERS += \
|
||||||
|
compilationdatabasetests.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
compilationdatabasetests.cpp
|
||||||
|
|
||||||
|
RESOURCES += compilationdatabasetests.qrc
|
||||||
|
}
|
||||||
|
@@ -13,7 +13,26 @@ QtcPlugin {
|
|||||||
"compilationdatabaseconstants.h",
|
"compilationdatabaseconstants.h",
|
||||||
"compilationdatabaseproject.cpp",
|
"compilationdatabaseproject.cpp",
|
||||||
"compilationdatabaseproject.h",
|
"compilationdatabaseproject.h",
|
||||||
|
"compilationdatabaseutils.cpp",
|
||||||
|
"compilationdatabaseutils.h",
|
||||||
"compilationdatabaseprojectmanagerplugin.cpp",
|
"compilationdatabaseprojectmanagerplugin.cpp",
|
||||||
"compilationdatabaseprojectmanagerplugin.h",
|
"compilationdatabaseprojectmanagerplugin.h",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
Group {
|
||||||
|
name: "Tests"
|
||||||
|
condition: qtc.testsEnabled
|
||||||
|
files: [
|
||||||
|
"compilationdatabasetests.cpp",
|
||||||
|
"compilationdatabasetests.h",
|
||||||
|
"compilationdatabasetests.qrc",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Group {
|
||||||
|
name: "Test resources"
|
||||||
|
prefix: "database_samples/"
|
||||||
|
fileTags: []
|
||||||
|
files: ["**/*"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "compilationdatabaseconstants.h"
|
#include "compilationdatabaseconstants.h"
|
||||||
#include "compilationdatabaseproject.h"
|
#include "compilationdatabaseproject.h"
|
||||||
|
#include "compilationdatabasetests.h"
|
||||||
|
|
||||||
#include <coreplugin/fileiconprovider.h>
|
#include <coreplugin/fileiconprovider.h>
|
||||||
#include <projectexplorer/projectmanager.h>
|
#include <projectexplorer/projectmanager.h>
|
||||||
@@ -52,5 +53,14 @@ void CompilationDatabaseProjectManagerPlugin::extensionsInitialized()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<QObject *> CompilationDatabaseProjectManagerPlugin::createTestObjects() const
|
||||||
|
{
|
||||||
|
QList<QObject *> tests;
|
||||||
|
#ifdef WITH_TESTS
|
||||||
|
tests << new CompilationDatabaseTests;
|
||||||
|
#endif
|
||||||
|
return tests;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace CompilationDatabaseProjectManager
|
} // namespace CompilationDatabaseProjectManager
|
||||||
|
@@ -43,6 +43,8 @@ public:
|
|||||||
bool initialize(const QStringList &arguments, QString *errorMessage) final;
|
bool initialize(const QStringList &arguments, QString *errorMessage) final;
|
||||||
void extensionsInitialized() final;
|
void extensionsInitialized() final;
|
||||||
private:
|
private:
|
||||||
|
QList<QObject *> createTestObjects() const final;
|
||||||
|
|
||||||
CompilationDatabaseEditorFactory factory;
|
CompilationDatabaseEditorFactory factory;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -0,0 +1,105 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2018 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "compilationdatabasetests.h"
|
||||||
|
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
#include <cpptools/cpptoolstestcase.h>
|
||||||
|
#include <cpptools/projectinfo.h>
|
||||||
|
#include <projectexplorer/kitinformation.h>
|
||||||
|
#include <projectexplorer/kitmanager.h>
|
||||||
|
#include <projectexplorer/projectexplorer.h>
|
||||||
|
#include <projectexplorer/toolchain.h>
|
||||||
|
#include <projectexplorer/toolchainmanager.h>
|
||||||
|
|
||||||
|
#include <QtTest>
|
||||||
|
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
namespace CompilationDatabaseProjectManager {
|
||||||
|
|
||||||
|
CompilationDatabaseTests::CompilationDatabaseTests(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
CompilationDatabaseTests::~CompilationDatabaseTests() = default;
|
||||||
|
|
||||||
|
void CompilationDatabaseTests::initTestCase()
|
||||||
|
{
|
||||||
|
const QList<Kit *> allKits = KitManager::kits();
|
||||||
|
if (allKits.empty())
|
||||||
|
QSKIP("This test requires at least one kit to be present.");
|
||||||
|
|
||||||
|
ToolChain *toolchain = ToolChainManager::toolChain([](const ToolChain *tc) {
|
||||||
|
return tc->isValid() && tc->language() == Constants::CXX_LANGUAGE_ID;
|
||||||
|
});
|
||||||
|
if (!toolchain)
|
||||||
|
QSKIP("This test requires that there is at least one C++ toolchain present.");
|
||||||
|
|
||||||
|
m_tmpDir = std::make_unique<CppTools::Tests::TemporaryCopiedDir>(":/database_samples");
|
||||||
|
QVERIFY(m_tmpDir->isValid());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompilationDatabaseTests::cleanupTestCase()
|
||||||
|
{
|
||||||
|
m_tmpDir.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompilationDatabaseTests::testProject()
|
||||||
|
{
|
||||||
|
QFETCH(QString, projectFilePath);
|
||||||
|
|
||||||
|
CppTools::Tests::ProjectOpenerAndCloser projectManager;
|
||||||
|
const CppTools::ProjectInfo projectInfo = projectManager.open(projectFilePath, true);
|
||||||
|
QVERIFY(projectInfo.isValid());
|
||||||
|
|
||||||
|
projectInfo.projectParts();
|
||||||
|
QVector<CppTools::ProjectPart::Ptr> projectParts = projectInfo.projectParts();
|
||||||
|
QVERIFY(!projectParts.isEmpty());
|
||||||
|
|
||||||
|
CppTools::ProjectPart &projectPart = *projectParts.first();
|
||||||
|
QVERIFY(!projectPart.headerPaths.isEmpty());
|
||||||
|
QVERIFY(!projectPart.projectMacros.isEmpty());
|
||||||
|
QVERIFY(!projectPart.toolChainMacros.isEmpty());
|
||||||
|
QVERIFY(!projectPart.files.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompilationDatabaseTests::testProject_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("projectFilePath");
|
||||||
|
|
||||||
|
addTestRow("qtc/compile_commands.json");
|
||||||
|
addTestRow("llvm/compile_commands.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompilationDatabaseTests::addTestRow(const QByteArray &relativeFilePath)
|
||||||
|
{
|
||||||
|
const QString absoluteFilePath = m_tmpDir->absolutePath(relativeFilePath);
|
||||||
|
const QString fileName = QFileInfo(absoluteFilePath).fileName();
|
||||||
|
|
||||||
|
QTest::newRow(fileName.toUtf8().constData()) << absoluteFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace CompilationDatabaseProjectManager
|
@@ -0,0 +1,54 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2018 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace CppTools { namespace Tests { class TemporaryCopiedDir; } }
|
||||||
|
|
||||||
|
namespace CompilationDatabaseProjectManager {
|
||||||
|
|
||||||
|
class CompilationDatabaseTests : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit CompilationDatabaseTests(QObject *parent = nullptr);
|
||||||
|
~CompilationDatabaseTests();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void initTestCase();
|
||||||
|
void cleanupTestCase();
|
||||||
|
void testProject();
|
||||||
|
void testProject_data();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void addTestRow(const QByteArray &relativeFilePath);
|
||||||
|
|
||||||
|
std::unique_ptr<CppTools::Tests::TemporaryCopiedDir> m_tmpDir;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace CompilationDatabaseProjectManager
|
@@ -0,0 +1,6 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file>database_samples/llvm/compile_commands.json</file>
|
||||||
|
<file>database_samples/qtc/compile_commands.json</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
@@ -0,0 +1,7 @@
|
|||||||
|
INCLUDEPATH += $$PWD
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/compilationdatabaseutils.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/compilationdatabaseutils.h
|
@@ -0,0 +1,216 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2018 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "compilationdatabaseutils.h"
|
||||||
|
|
||||||
|
#include <projectexplorer/headerpath.h>
|
||||||
|
#include <projectexplorer/projectmacro.h>
|
||||||
|
|
||||||
|
#include <utils/hostosinfo.h>
|
||||||
|
#include <utils/optional.h>
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
|
namespace CompilationDatabaseProjectManager {
|
||||||
|
|
||||||
|
static QString updatedPathFlag(const QString &pathStr, const QString &workingDir)
|
||||||
|
{
|
||||||
|
QString result = pathStr;
|
||||||
|
if (!QDir(pathStr).exists()
|
||||||
|
&& QDir(workingDir + "/" + pathStr).exists()) {
|
||||||
|
result = workingDir + "/" + pathStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CppTools::ProjectFile::Kind fileKindFromString(const QString &flag)
|
||||||
|
{
|
||||||
|
using namespace CppTools;
|
||||||
|
if (flag == "c++-header")
|
||||||
|
return ProjectFile::CXXHeader;
|
||||||
|
if (flag == "c-header")
|
||||||
|
return ProjectFile::CHeader;
|
||||||
|
if (flag == "c++" || flag == "/TP" || flag.startsWith("/Tp"))
|
||||||
|
return ProjectFile::CXXSource;
|
||||||
|
if (flag == "c" || flag == "/TC" || flag.startsWith("/Tc"))
|
||||||
|
return ProjectFile::CSource;
|
||||||
|
|
||||||
|
if (flag == "objective-c++")
|
||||||
|
return ProjectFile::ObjCXXSource;
|
||||||
|
if (flag == "objective-c++-header")
|
||||||
|
return ProjectFile::ObjCXXHeader;
|
||||||
|
if (flag == "objective-c")
|
||||||
|
return ProjectFile::ObjCSource;
|
||||||
|
if (flag == "objective-c-header")
|
||||||
|
return ProjectFile::ObjCHeader;
|
||||||
|
|
||||||
|
if (flag == "cl")
|
||||||
|
return ProjectFile::OpenCLSource;
|
||||||
|
if (flag == "cuda")
|
||||||
|
return ProjectFile::CudaSource;
|
||||||
|
|
||||||
|
return ProjectFile::Unclassified;
|
||||||
|
}
|
||||||
|
|
||||||
|
void filteredFlags(const QString &fileName,
|
||||||
|
const QString &workingDir,
|
||||||
|
QStringList &flags,
|
||||||
|
HeaderPaths &headerPaths,
|
||||||
|
Macros ¯os,
|
||||||
|
CppTools::ProjectFile::Kind &fileKind)
|
||||||
|
{
|
||||||
|
if (flags.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Skip compiler call if present.
|
||||||
|
bool skipNext = Utils::HostOsInfo::isWindowsHost()
|
||||||
|
? (!flags.first().startsWith('/') && !flags.first().startsWith('-'))
|
||||||
|
: (!flags.first().startsWith('-'));
|
||||||
|
Utils::optional<HeaderPathType> includePathType;
|
||||||
|
Utils::optional<MacroType> macroType;
|
||||||
|
bool fileKindIsNext = false;
|
||||||
|
|
||||||
|
QStringList filtered;
|
||||||
|
for (const QString &flag : flags) {
|
||||||
|
if (skipNext) {
|
||||||
|
skipNext = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includePathType) {
|
||||||
|
const QString pathStr = updatedPathFlag(flag, workingDir);
|
||||||
|
headerPaths.append({pathStr, includePathType.value()});
|
||||||
|
includePathType.reset();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (macroType) {
|
||||||
|
Macro macro = Macro::fromKeyValue(flag);
|
||||||
|
macro.type = macroType.value();
|
||||||
|
macros.append(macro);
|
||||||
|
macroType.reset();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileKindIsNext || flag == "/TC" || flag == "/TP"
|
||||||
|
|| flag.startsWith("/Tc") || flag.startsWith("/Tp")) {
|
||||||
|
fileKindIsNext = false;
|
||||||
|
fileKind = fileKindFromString(flag);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag == "-x") {
|
||||||
|
fileKindIsNext = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag == "-c" || flag == "-pedantic"
|
||||||
|
|| flag.startsWith("-O") || flag.startsWith("-W") || flag.startsWith("-w")
|
||||||
|
|| QString::compare(flag, "-fpic", Qt::CaseInsensitive) == 0
|
||||||
|
|| QString::compare(flag, "-fpie", Qt::CaseInsensitive) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag.endsWith(fileName))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((flag.startsWith("-I") || flag.startsWith("-isystem") || flag.startsWith("/I"))
|
||||||
|
&& flag != "-I" && flag != "-isystem" && flag != "/I") {
|
||||||
|
bool userInclude = flag.startsWith("-I");
|
||||||
|
const QString pathStr = updatedPathFlag(flag.mid(userInclude ? 2 : 8),
|
||||||
|
workingDir);
|
||||||
|
headerPaths.append({pathStr, userInclude
|
||||||
|
? HeaderPathType::User
|
||||||
|
: HeaderPathType::System});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flag.startsWith("-D") || flag.startsWith("-U") || flag.startsWith("/D") || flag.startsWith("/U"))
|
||||||
|
&& flag != "-D" && flag != "-U" && flag != "/D" && flag != "/U") {
|
||||||
|
Macro macro = Macro::fromKeyValue(flag.mid(2));
|
||||||
|
macro.type = (flag.startsWith("-D") || flag.startsWith("/D")) ? MacroType::Define : MacroType::Undefine;
|
||||||
|
macros.append(macro);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag == "-I" || flag == "-isystem" || flag == "/I") {
|
||||||
|
includePathType = (flag != "-isystem") ? HeaderPathType::User : HeaderPathType::System;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flag == "-D" || flag == "-U" || flag == "/D" || flag == "/U") {
|
||||||
|
macroType = (flag == "-D" || flag == "/D") ? MacroType::Define : MacroType::Undefine;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flag.startsWith("-std=") || flag.startsWith("/std:"))
|
||||||
|
&& fileKind == CppTools::ProjectFile::Unclassified) {
|
||||||
|
const bool cpp = (flag.contains("c++") || flag.contains("gnu++"));
|
||||||
|
if (CppTools::ProjectFile::isHeader(CppTools::ProjectFile::classify(fileName)))
|
||||||
|
fileKind = cpp ? CppTools::ProjectFile::CXXHeader : CppTools::ProjectFile::CHeader;
|
||||||
|
else
|
||||||
|
fileKind = cpp ? CppTools::ProjectFile::CXXSource : CppTools::ProjectFile::CXXHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip all remaining Windows flags except feature flags.
|
||||||
|
if (flag.startsWith("/") && !flag.startsWith("/Z"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
filtered.push_back(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileKind == CppTools::ProjectFile::Unclassified)
|
||||||
|
fileKind = CppTools::ProjectFile::classify(fileName);
|
||||||
|
|
||||||
|
flags = filtered;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList splitCommandLine(QString commandLine)
|
||||||
|
{
|
||||||
|
QStringList result;
|
||||||
|
bool insideQuotes = false;
|
||||||
|
|
||||||
|
// Remove escaped quotes.
|
||||||
|
commandLine.replace("\\\"", "'");
|
||||||
|
for (const QString &part : commandLine.split(QRegularExpression("\""))) {
|
||||||
|
if (insideQuotes) {
|
||||||
|
const QString quotedPart = "\"" + part + "\"";
|
||||||
|
if (result.last().endsWith("="))
|
||||||
|
result.last().append(quotedPart);
|
||||||
|
else
|
||||||
|
result.append(quotedPart);
|
||||||
|
} else { // If 's' is outside quotes ...
|
||||||
|
result.append(part.split(QRegularExpression("\\s+"), QString::SkipEmptyParts));
|
||||||
|
}
|
||||||
|
insideQuotes = !insideQuotes;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace CompilationDatabaseProjectManager
|
@@ -0,0 +1,50 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2018 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "compilationdatabaseconstants.h"
|
||||||
|
|
||||||
|
#include <cpptools/cppprojectfile.h>
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
namespace ProjectExplorer {
|
||||||
|
class HeaderPath;
|
||||||
|
class Macro;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CompilationDatabaseProjectManager {
|
||||||
|
|
||||||
|
void filteredFlags(const QString &fileName,
|
||||||
|
const QString &workingDir,
|
||||||
|
QStringList &flags,
|
||||||
|
QVector<ProjectExplorer::HeaderPath> &headerPaths,
|
||||||
|
QVector<ProjectExplorer::Macro> ¯os,
|
||||||
|
CppTools::ProjectFile::Kind &fileKind);
|
||||||
|
|
||||||
|
QStringList splitCommandLine(QString commandLine);
|
||||||
|
|
||||||
|
} // namespace CompilationDatabaseProjectManager
|
@@ -0,0 +1,7 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"directory": "C:/build-qt_llvm-msvc2017_64bit-Debug",
|
||||||
|
"command": "C:\\PROGRA~2\\MICROS~2\\2017\\COMMUN~1\\VC\\Tools\\MSVC\\1415~1.267\\bin\\HostX64\\x64\\cl.exe /nologo /TP -DUNICODE -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_GNU_SOURCE -D_HAS_EXCEPTIONS=0 -D_SCL_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_WARNINGS -D_UNICODE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Dclang=clang_qtcreator -Dllvm=llvm_qtcreator -Itools\\clang\\lib\\Sema -IC:\\qt_llvm\\tools\\clang\\lib\\Sema -IC:\\qt_llvm\\tools\\clang\\include -Itools\\clang\\include -Iinclude -IC:\\qt_llvm\\include /DWIN32 /D_WINDOWS /Zc:inline /Zc:strictStrings /Oi /Zc:rvalueCast /W4 -wd4141 -wd4146 -wd4180 -wd4244 -wd4258 -wd4267 -wd4291 -wd4345 -wd4351 -wd4355 -wd4456 -wd4457 -wd4458 -wd4459 -wd4503 -wd4624 -wd4722 -wd4800 -wd4100 -wd4127 -wd4512 -wd4505 -wd4610 -wd4510 -wd4702 -wd4245 -wd4706 -wd4310 -wd4701 -wd4703 -wd4389 -wd4611 -wd4805 -wd4204 -wd4577 -wd4091 -wd4592 -wd4319 -wd4324 -w14062 -we4238 /MDd /Zi /Ob0 /Od /RTC1 /EHs-c- /GR /Fotools\\clang\\lib\\Sema\\CMakeFiles\\clangSema.dir\\SemaCodeComplete.cpp.obj /FdTARGET_COMPILE_PDB /FS -c C:\\qt_llvm\\tools\\clang\\lib\\Sema\\SemaCodeComplete.cpp",
|
||||||
|
"file": "C:\\qt_llvm\\tools\\clang\\lib\\Sema\\SemaCodeComplete.cpp"
|
||||||
|
}
|
||||||
|
]
|
@@ -0,0 +1,62 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"arguments": [
|
||||||
|
"clang++",
|
||||||
|
"-c",
|
||||||
|
"-m32",
|
||||||
|
"-target",
|
||||||
|
"i686-w64-mingw32",
|
||||||
|
"-std=gnu++14",
|
||||||
|
"-fcxx-exceptions",
|
||||||
|
"-fexceptions",
|
||||||
|
"-DUNICODE",
|
||||||
|
"-D_UNICODE",
|
||||||
|
"-DCPPTOOLS_LIBRARY",
|
||||||
|
"-DWITH_TESTS",
|
||||||
|
"-DRELATIVE_PLUGIN_PATH=\"../lib/qtcreator/plugins\"",
|
||||||
|
"-DRELATIVE_LIBEXEC_PATH=\".\"",
|
||||||
|
"-DRELATIVE_DATA_PATH=\"../share/qtcreator\"",
|
||||||
|
"-DRELATIVE_DOC_PATH=\"../share/doc/qtcreator\"",
|
||||||
|
"-DIDE_LIBRARY_BASENAME=\"lib\"",
|
||||||
|
"-DQT_CREATOR",
|
||||||
|
"-DQT_NO_CAST_TO_ASCII",
|
||||||
|
"-DQT_RESTRICTED_CAST_FROM_ASCII",
|
||||||
|
"-DQT_DISABLE_DEPRECATED_BEFORE=0x050600",
|
||||||
|
"-DQT_USE_FAST_OPERATOR_PLUS",
|
||||||
|
"-DQT_USE_FAST_CONCATENATION",
|
||||||
|
"-DSRCDIR=\"C:/qt-creator/src/plugins/cpptools\"",
|
||||||
|
"-DQT_QML_DEBUG",
|
||||||
|
"-DQT_PLUGIN",
|
||||||
|
"-DQT_WIDGETS_LIB",
|
||||||
|
"-DQT_GUI_LIB",
|
||||||
|
"-DQT_TESTLIB_LIB",
|
||||||
|
"-DQT_CONCURRENT_LIB",
|
||||||
|
"-DQT_NETWORK_LIB",
|
||||||
|
"-DQT_CORE_LIB",
|
||||||
|
"-fPIC",
|
||||||
|
"-I",
|
||||||
|
"C:\\Qt\\5.9.2\\mingw53_32\\include",
|
||||||
|
"-I",
|
||||||
|
"C:\\Qt\\5.9.2\\mingw53_32\\include\\QtWidgets",
|
||||||
|
"-I",
|
||||||
|
"C:\\Qt\\5.9.2\\mingw53_32\\include\\QtGui",
|
||||||
|
"-I",
|
||||||
|
"C:\\Qt\\5.9.2\\mingw53_32\\include\\QtANGLE",
|
||||||
|
"-I",
|
||||||
|
"C:\\Qt\\5.9.2\\mingw53_32\\include\\QtTest",
|
||||||
|
"-I",
|
||||||
|
"C:\\Qt\\5.9.2\\mingw53_32\\include\\QtConcurrent",
|
||||||
|
"-I",
|
||||||
|
"C:\\Qt\\5.9.2\\mingw53_32\\include\\QtNetwork",
|
||||||
|
"-I",
|
||||||
|
"C:\\Qt\\5.9.2\\mingw53_32\\include\\QtCore",
|
||||||
|
"-I",
|
||||||
|
"C:\\Qt\\5.9.2\\mingw53_32\\mkspecs\\win32-g++",
|
||||||
|
"-x",
|
||||||
|
"c++",
|
||||||
|
"C:\\qt-creator\\src\\plugins\\cpptools\\compileroptionsbuilder.cpp"
|
||||||
|
],
|
||||||
|
"directory": "C:/build-qtcreator-MinGW_32bit-Debug",
|
||||||
|
"file": "C:/qt-creator/src/plugins/cpptools/compileroptionsbuilder.cpp"
|
||||||
|
}
|
||||||
|
]
|
@@ -76,13 +76,6 @@ QStringList CompilerOptionsBuilder::build(CppTools::ProjectFile::Kind fileKind,
|
|||||||
addTargetTriple();
|
addTargetTriple();
|
||||||
addExtraCodeModelFlags();
|
addExtraCodeModelFlags();
|
||||||
|
|
||||||
if (m_projectPart.toolchainType
|
|
||||||
== ProjectExplorer::Constants::COMPILATION_DATABASE_TOOLCHAIN_TYPEID) {
|
|
||||||
addHeaderPathOptions();
|
|
||||||
insertWrappedQtHeaders();
|
|
||||||
return options();
|
|
||||||
}
|
|
||||||
|
|
||||||
updateLanguageOption(fileKind);
|
updateLanguageOption(fileKind);
|
||||||
addOptionsForLanguage(/*checkForBorlandExtensions*/ true);
|
addOptionsForLanguage(/*checkForBorlandExtensions*/ true);
|
||||||
enableExceptions();
|
enableExceptions();
|
||||||
|
@@ -165,9 +165,6 @@ ProjectPart::Ptr ProjectInfoGenerator::createProjectPart(
|
|||||||
part->warningFlags = flags.warningFlags;
|
part->warningFlags = flags.warningFlags;
|
||||||
part->languageExtensions = flags.languageExtensions;
|
part->languageExtensions = flags.languageExtensions;
|
||||||
|
|
||||||
if (part->toolchainType == ProjectExplorer::Constants::COMPILATION_DATABASE_TOOLCHAIN_TYPEID)
|
|
||||||
part->extraCodeModelFlags = flags.commandLineFlags;
|
|
||||||
|
|
||||||
// Toolchain macros and language version
|
// Toolchain macros and language version
|
||||||
if (tcInfo.macroInspectionRunner) {
|
if (tcInfo.macroInspectionRunner) {
|
||||||
auto macroInspectionReport = tcInfo.macroInspectionRunner(flags.commandLineFlags);
|
auto macroInspectionReport = tcInfo.macroInspectionRunner(flags.commandLineFlags);
|
||||||
|
@@ -163,7 +163,6 @@ const char MINGW_TOOLCHAIN_TYPEID[] = "ProjectExplorer.ToolChain.Mingw";
|
|||||||
const char MSVC_TOOLCHAIN_TYPEID[] = "ProjectExplorer.ToolChain.Msvc";
|
const char MSVC_TOOLCHAIN_TYPEID[] = "ProjectExplorer.ToolChain.Msvc";
|
||||||
const char CLANG_CL_TOOLCHAIN_TYPEID[] = "ProjectExplorer.ToolChain.ClangCl";
|
const char CLANG_CL_TOOLCHAIN_TYPEID[] = "ProjectExplorer.ToolChain.ClangCl";
|
||||||
const char CUSTOM_TOOLCHAIN_TYPEID[] = "ProjectExplorer.ToolChain.Custom";
|
const char CUSTOM_TOOLCHAIN_TYPEID[] = "ProjectExplorer.ToolChain.Custom";
|
||||||
const char COMPILATION_DATABASE_TOOLCHAIN_TYPEID[] = "ProjectExplorer.ToolChain.Empty";
|
|
||||||
|
|
||||||
// Default directory to run custom (build) commands in.
|
// Default directory to run custom (build) commands in.
|
||||||
const char DEFAULT_WORKING_DIR[] = "%{buildDir}";
|
const char DEFAULT_WORKING_DIR[] = "%{buildDir}";
|
||||||
|
169
tests/unit/unittest/compilationdatabaseutils-test.cpp
Normal file
169
tests/unit/unittest/compilationdatabaseutils-test.cpp
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2018 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "googletest.h"
|
||||||
|
|
||||||
|
#include <compilationdatabaseprojectmanager/compilationdatabaseutils.h>
|
||||||
|
#include <projectexplorer/headerpath.h>
|
||||||
|
#include <projectexplorer/projectmacro.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
using namespace CompilationDatabaseProjectManager;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class CompilationDatabaseUtils : public ::testing::Test
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
HeaderPaths headerPaths;
|
||||||
|
Macros macros;
|
||||||
|
CppTools::ProjectFile::Kind fileKind = CppTools::ProjectFile::Unclassified;
|
||||||
|
QStringList flags;
|
||||||
|
QString fileName;
|
||||||
|
QString workingDir;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(CompilationDatabaseUtils, FilterEmptyFlags)
|
||||||
|
{
|
||||||
|
filteredFlags(fileName, workingDir, flags, headerPaths, macros, fileKind);
|
||||||
|
|
||||||
|
ASSERT_THAT(flags.isEmpty(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CompilationDatabaseUtils, FilterArguments)
|
||||||
|
{
|
||||||
|
fileName = "compileroptionsbuilder.cpp";
|
||||||
|
workingDir = "C:/build-qtcreator-MinGW_32bit-Debug";
|
||||||
|
flags = QStringList {
|
||||||
|
"clang++",
|
||||||
|
"-c",
|
||||||
|
"-m32",
|
||||||
|
"-target",
|
||||||
|
"i686-w64-mingw32",
|
||||||
|
"-std=gnu++14",
|
||||||
|
"-fcxx-exceptions",
|
||||||
|
"-fexceptions",
|
||||||
|
"-DUNICODE",
|
||||||
|
"-DRELATIVE_PLUGIN_PATH=\"../lib/qtcreator/plugins\"",
|
||||||
|
"-DQT_CREATOR",
|
||||||
|
"-fPIC",
|
||||||
|
"-I",
|
||||||
|
"C:\\Qt\\5.9.2\\mingw53_32\\include",
|
||||||
|
"-I",
|
||||||
|
"C:\\Qt\\5.9.2\\mingw53_32\\include\\QtWidgets",
|
||||||
|
"-x",
|
||||||
|
"c++",
|
||||||
|
"C:\\qt-creator\\src\\plugins\\cpptools\\compileroptionsbuilder.cpp"
|
||||||
|
};
|
||||||
|
|
||||||
|
filteredFlags(fileName, workingDir, flags, headerPaths, macros, fileKind);
|
||||||
|
|
||||||
|
ASSERT_THAT(flags, Eq(QStringList{"-m32",
|
||||||
|
"-target",
|
||||||
|
"i686-w64-mingw32",
|
||||||
|
"-std=gnu++14",
|
||||||
|
"-fcxx-exceptions",
|
||||||
|
"-fexceptions"}));
|
||||||
|
ASSERT_THAT(headerPaths, Eq(HeaderPaths{
|
||||||
|
{"C:\\Qt\\5.9.2\\mingw53_32\\include", HeaderPathType::User},
|
||||||
|
{"C:\\Qt\\5.9.2\\mingw53_32\\include\\QtWidgets", HeaderPathType::User}
|
||||||
|
}));
|
||||||
|
ASSERT_THAT(macros, Eq(Macros{
|
||||||
|
{"UNICODE", "1"},
|
||||||
|
{"RELATIVE_PLUGIN_PATH", "\"../lib/qtcreator/plugins\""},
|
||||||
|
{"QT_CREATOR", "1"}
|
||||||
|
}));
|
||||||
|
ASSERT_THAT(fileKind, CppTools::ProjectFile::Kind::CXXSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
static QString kCmakeCommand = "C:\\PROGRA~2\\MICROS~2\\2017\\COMMUN~1\\VC\\Tools\\MSVC\\1415~1.267\\bin\\HostX64\\x64\\cl.exe "
|
||||||
|
"/nologo "
|
||||||
|
"/TP "
|
||||||
|
"-DUNICODE "
|
||||||
|
"-D_HAS_EXCEPTIONS=0 "
|
||||||
|
"-Itools\\clang\\lib\\Sema "
|
||||||
|
"/DWIN32 "
|
||||||
|
"/D_WINDOWS "
|
||||||
|
"/Zc:inline "
|
||||||
|
"/Zc:strictStrings "
|
||||||
|
"/Oi "
|
||||||
|
"/Zc:rvalueCast "
|
||||||
|
"/W4 "
|
||||||
|
"-wd4141 "
|
||||||
|
"-wd4146 "
|
||||||
|
"/MDd "
|
||||||
|
"/Zi "
|
||||||
|
"/Ob0 "
|
||||||
|
"/Od "
|
||||||
|
"/RTC1 "
|
||||||
|
"/EHs-c- "
|
||||||
|
"/GR "
|
||||||
|
"/Fotools\\clang\\lib\\Sema\\CMakeFiles\\clangSema.dir\\SemaCodeComplete.cpp.obj "
|
||||||
|
"/FdTARGET_COMPILE_PDB "
|
||||||
|
"/FS "
|
||||||
|
"-c "
|
||||||
|
"C:\\qt_llvm\\tools\\clang\\lib\\Sema\\SemaCodeComplete.cpp";
|
||||||
|
|
||||||
|
TEST_F(CompilationDatabaseUtils, SplitFlags)
|
||||||
|
{
|
||||||
|
flags = splitCommandLine(kCmakeCommand);
|
||||||
|
|
||||||
|
ASSERT_THAT(flags.size(), 27);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CompilationDatabaseUtils, SplitFlagsWithEscapedQuotes)
|
||||||
|
{
|
||||||
|
flags = splitCommandLine("-DRC_FILE_VERSION=\\\"7.0.0\\\" "
|
||||||
|
"-DRELATIVE_PLUGIN_PATH=\"../lib/qtcreator/plugins\"");
|
||||||
|
|
||||||
|
ASSERT_THAT(flags.size(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(CompilationDatabaseUtils, FilterCommand)
|
||||||
|
{
|
||||||
|
fileName = "SemaCodeComplete.cpp";
|
||||||
|
workingDir = "C:/build-qt_llvm-msvc2017_64bit-Debug";
|
||||||
|
flags = splitCommandLine(kCmakeCommand);
|
||||||
|
|
||||||
|
filteredFlags(fileName, workingDir, flags, headerPaths, macros, fileKind);
|
||||||
|
|
||||||
|
ASSERT_THAT(flags, Eq(QStringList{"/Zc:inline",
|
||||||
|
"/Zc:strictStrings",
|
||||||
|
"/Zc:rvalueCast",
|
||||||
|
"/Zi"}));
|
||||||
|
ASSERT_THAT(headerPaths, Eq(HeaderPaths{
|
||||||
|
{"tools\\clang\\lib\\Sema", HeaderPathType::User}
|
||||||
|
}));
|
||||||
|
ASSERT_THAT(macros, Eq(Macros{
|
||||||
|
{"UNICODE", "1"},
|
||||||
|
{"_HAS_EXCEPTIONS", "0"},
|
||||||
|
{"WIN32", "1"},
|
||||||
|
{"_WINDOWS", "1"}
|
||||||
|
}));
|
||||||
|
ASSERT_THAT(fileKind, CppTools::ProjectFile::Kind::CXXSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -13,6 +13,7 @@ include($$PWD/../../../src/tools/clangpchmanagerbackend/source/clangpchmanagerba
|
|||||||
include($$PWD/../../../src/plugins/clangrefactoring/clangrefactoring-source.pri)
|
include($$PWD/../../../src/plugins/clangrefactoring/clangrefactoring-source.pri)
|
||||||
include($$PWD/../../../src/plugins/clangpchmanager/clangpchmanager-source.pri)
|
include($$PWD/../../../src/plugins/clangpchmanager/clangpchmanager-source.pri)
|
||||||
include($$PWD/../../../src/plugins/cpptools/cpptoolsunittestfiles.pri)
|
include($$PWD/../../../src/plugins/cpptools/cpptoolsunittestfiles.pri)
|
||||||
|
include($$PWD/../../../src/plugins/compilationdatabaseprojectmanager/compilationdatabaseunittestfiles.pri)
|
||||||
include(cplusplus.pri)
|
include(cplusplus.pri)
|
||||||
!isEmpty(LLVM_VERSION) {
|
!isEmpty(LLVM_VERSION) {
|
||||||
include($$PWD/../../../src/shared/clang/clang_defines.pri)
|
include($$PWD/../../../src/shared/clang/clang_defines.pri)
|
||||||
|
@@ -104,7 +104,8 @@ SOURCES += \
|
|||||||
taskscheduler-test.cpp \
|
taskscheduler-test.cpp \
|
||||||
compileroptionsbuilder-test.cpp \
|
compileroptionsbuilder-test.cpp \
|
||||||
usedmacroandsourcestorage-test.cpp \
|
usedmacroandsourcestorage-test.cpp \
|
||||||
pchtaskgenerator-test.cpp
|
pchtaskgenerator-test.cpp \
|
||||||
|
compilationdatabaseutils-test.cpp
|
||||||
|
|
||||||
!isEmpty(LIBCLANG_LIBS) {
|
!isEmpty(LIBCLANG_LIBS) {
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
|
Reference in New Issue
Block a user