forked from qt-creator/qt-creator
Convert macros from plain QByteArray to a vector of structs
The old code model expected the macros as C++ formatted text ("#define Foo 42) but newer targets like the Clang codemodel expect key value arguments like "-DFoo=42". So instead of parsing the text again and again we use an abstract data description. Task-number: QTCREATORBUG-17915 Change-Id: I0179fd13c48a581e91ee79bba9d42d501c26f19f Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
@@ -86,7 +86,7 @@ static bool qtTestLibDefined(const QString &fileName)
|
||||
const QList<CppTools::ProjectPart::Ptr> parts =
|
||||
CppTools::CppModelManager::instance()->projectPart(fileName);
|
||||
if (parts.size() > 0)
|
||||
return parts.at(0)->projectDefines.contains("#define QT_TESTLIB_LIB");
|
||||
return parts.at(0)->projectMacros.contains({"QT_TESTLIB_LIB"});
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -89,20 +89,21 @@ static bool includesQtQuickTest(const CPlusPlus::Document::Ptr &doc,
|
||||
static QString quickTestSrcDir(const CppTools::CppModelManager *cppMM,
|
||||
const QString &fileName)
|
||||
{
|
||||
static const QByteArray qtsd(" QUICK_TEST_SOURCE_DIR ");
|
||||
const QList<CppTools::ProjectPart::Ptr> parts = cppMM->projectPart(fileName);
|
||||
if (parts.size() > 0) {
|
||||
QByteArray projDefines(parts.at(0)->projectDefines);
|
||||
for (const QByteArray &line : projDefines.split('\n')) {
|
||||
if (line.contains(qtsd)) {
|
||||
QByteArray result = line.mid(line.indexOf(qtsd) + qtsd.length());
|
||||
if (result.startsWith('"'))
|
||||
result.remove(result.length() - 1, 1).remove(0, 1);
|
||||
if (result.startsWith("\\\""))
|
||||
result.remove(result.length() - 2, 2).remove(0, 2);
|
||||
return QLatin1String(result);
|
||||
}
|
||||
}
|
||||
const ProjectExplorer::Macros ¯os = parts.at(0)->projectMacros;
|
||||
auto found = std::find_if(
|
||||
macros.begin(),
|
||||
macros.end(),
|
||||
[] (const ProjectExplorer::Macro ¯o) { return macro.key == "QUICK_TEST_SOURCE_DIR"; });
|
||||
if (found != macros.end()) {
|
||||
QByteArray result = found->value;
|
||||
if (result.startsWith('"'))
|
||||
result.remove(result.length() - 1, 1).remove(0, 1);
|
||||
if (result.startsWith("\\\""))
|
||||
result.remove(result.length() - 2, 2).remove(0, 2);
|
||||
return QLatin1String(result);
|
||||
}
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
@@ -298,7 +298,7 @@ void AutotoolsProject::updateCppCodeModel()
|
||||
? target->activeBuildConfiguration()->buildDirectory().toString() : QString();
|
||||
|
||||
rpp.setIncludePaths(filterIncludes(absSrc, absBuild, m_makefileParserThread->includePaths()));
|
||||
rpp.setDefines(m_makefileParserThread->defines());
|
||||
rpp.setMacros(m_makefileParserThread->macros());
|
||||
rpp.setFiles(m_files);
|
||||
|
||||
m_cppCodeModelUpdater->update({this, cToolChain, cxxToolChain, k, {rpp}});
|
||||
|
@@ -108,9 +108,9 @@ QStringList MakefileParser::includePaths() const
|
||||
return m_includePaths;
|
||||
}
|
||||
|
||||
QByteArray MakefileParser::defines() const
|
||||
ProjectExplorer::Macros MakefileParser::macros() const
|
||||
{
|
||||
return m_defines;
|
||||
return m_macros;
|
||||
}
|
||||
|
||||
QStringList MakefileParser::cflags() const
|
||||
@@ -449,11 +449,7 @@ bool MakefileParser::maybeParseDefine(const QString &term)
|
||||
{
|
||||
if (term.startsWith(QLatin1String("-D"))) {
|
||||
QString def = term.mid(2); // remove the "-D"
|
||||
QByteArray data = def.toUtf8();
|
||||
int pos = data.indexOf('=');
|
||||
if (pos >= 0)
|
||||
data[pos] = ' ';
|
||||
m_defines += (QByteArray("#define ") + data + '\n');
|
||||
m_macros += ProjectExplorer::Macro::fromKeyValue(def);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@@ -27,10 +27,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
|
||||
#include <QMutex>
|
||||
#include <QStringList>
|
||||
#include <QTextStream>
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QDir)
|
||||
|
||||
@@ -49,6 +52,8 @@ class MakefileParser : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
using Macros = ProjectExplorer::Macros;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @param makefile Filename including path of the autotools
|
||||
@@ -98,7 +103,7 @@ public:
|
||||
* #define X12_HAS_DEPRECATED
|
||||
* @endcode
|
||||
*/
|
||||
QByteArray defines() const;
|
||||
Macros macros() const;
|
||||
|
||||
/**
|
||||
* @return List of compiler flags for C.
|
||||
@@ -267,7 +272,7 @@ private:
|
||||
QStringList m_sources; ///< Return value for MakefileParser::sources()
|
||||
QStringList m_makefiles; ///< Return value for MakefileParser::makefiles()
|
||||
QStringList m_includePaths; ///< Return value for MakefileParser::includePaths()
|
||||
QByteArray m_defines; ///< Return value for MakefileParser::defines()
|
||||
Macros m_macros; ///< Return value for MakefileParser::macros()
|
||||
QStringList m_cflags; ///< Return value for MakefileParser::cflags()
|
||||
QStringList m_cxxflags; ///< Return value for MakefileParser::cxxflags()
|
||||
QStringList m_cppflags; ///< The cpp flags, which will be part of both cflags and cxxflags
|
||||
|
@@ -61,10 +61,10 @@ QStringList MakefileParserThread::includePaths() const
|
||||
return m_includePaths;
|
||||
}
|
||||
|
||||
QByteArray MakefileParserThread::defines() const
|
||||
ProjectExplorer::Macros MakefileParserThread::macros() const
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
return m_defines;
|
||||
return m_macros;
|
||||
}
|
||||
|
||||
QStringList MakefileParserThread::cflags() const
|
||||
@@ -109,7 +109,7 @@ void MakefileParserThread::run()
|
||||
m_sources = m_parser.sources();
|
||||
m_makefiles = m_parser.makefiles();
|
||||
m_includePaths = m_parser.includePaths();
|
||||
m_defines = m_parser.defines();
|
||||
m_macros = m_parser.macros();
|
||||
m_cflags = m_parser.cflags();
|
||||
m_cxxflags = m_parser.cxxflags();
|
||||
}
|
||||
|
@@ -29,9 +29,12 @@
|
||||
|
||||
#include "makefileparser.h"
|
||||
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
|
||||
#include <QMutex>
|
||||
#include <QStringList>
|
||||
#include <QThread>
|
||||
#include <QVector>
|
||||
|
||||
namespace AutotoolsProjectManager {
|
||||
namespace Internal {
|
||||
@@ -47,6 +50,8 @@ class MakefileParserThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
using Macros = ProjectExplorer::Macros;
|
||||
|
||||
public:
|
||||
MakefileParserThread(const QString &makefile);
|
||||
|
||||
@@ -82,10 +87,10 @@ public:
|
||||
QStringList includePaths() const;
|
||||
|
||||
/**
|
||||
* @return Concatenated defines. Should be invoked, after the signal
|
||||
* @return Concatenated macros. Should be invoked, after the signal
|
||||
* finished() has been emitted.
|
||||
*/
|
||||
QByteArray defines() const;
|
||||
Macros macros() const;
|
||||
|
||||
/**
|
||||
* @return List of compiler flags for C. Should be invoked, after the signal
|
||||
@@ -134,7 +139,7 @@ private:
|
||||
QStringList m_sources; ///< Return value for MakefileParserThread::sources()
|
||||
QStringList m_makefiles; ///< Return value for MakefileParserThread::makefiles()
|
||||
QStringList m_includePaths; ///< Return value for MakefileParserThread::includePaths()
|
||||
QByteArray m_defines; ///< Return value for MakefileParserThread::defines()
|
||||
Macros m_macros; ///< Return value for MakefileParserThread::macros()
|
||||
QStringList m_cflags; ///< Return value for MakefileParserThread::cflags()
|
||||
QStringList m_cxxflags; ///< Return value for MakefileParserThread::cxxflags()
|
||||
};
|
||||
|
@@ -512,7 +512,7 @@ bool OpenEditorAtCursorPosition::waitUntil(const std::function<bool ()> &conditi
|
||||
}
|
||||
|
||||
CppTools::ProjectPart::Ptr createProjectPart(const QStringList &files,
|
||||
const QString &defines)
|
||||
const ProjectExplorer::Macros ¯os)
|
||||
{
|
||||
using namespace CppTools;
|
||||
|
||||
@@ -521,19 +521,19 @@ CppTools::ProjectPart::Ptr createProjectPart(const QStringList &files,
|
||||
foreach (const QString &file, files)
|
||||
projectPart->files.append(ProjectFile(file, ProjectFile::classify(file)));
|
||||
projectPart->qtVersion = ProjectPart::NoQt;
|
||||
projectPart->projectDefines = defines.toUtf8();
|
||||
projectPart->projectMacros = macros;
|
||||
|
||||
return projectPart;
|
||||
}
|
||||
|
||||
CppTools::ProjectInfo createProjectInfo(ProjectExplorer::Project *project,
|
||||
const QStringList &files,
|
||||
const QString &defines)
|
||||
const ProjectExplorer::Macros ¯os)
|
||||
{
|
||||
using namespace CppTools;
|
||||
QTC_ASSERT(project, return ProjectInfo());
|
||||
|
||||
const CppTools::ProjectPart::Ptr projectPart = createProjectPart(files, defines);
|
||||
const CppTools::ProjectPart::Ptr projectPart = createProjectPart(files, macros);
|
||||
ProjectInfo projectInfo = ProjectInfo(project);
|
||||
projectInfo.appendProjectPart(projectPart);
|
||||
return projectInfo;
|
||||
@@ -543,11 +543,11 @@ class ProjectLoader
|
||||
{
|
||||
public:
|
||||
ProjectLoader(const QStringList &projectFiles,
|
||||
const QString &projectDefines,
|
||||
const ProjectExplorer::Macros &projectMacros,
|
||||
bool testOnlyForCleanedProjects = false)
|
||||
: m_project(0)
|
||||
, m_projectFiles(projectFiles)
|
||||
, m_projectDefines(projectDefines)
|
||||
, m_projectMacros(projectMacros)
|
||||
, m_helper(0, testOnlyForCleanedProjects)
|
||||
{
|
||||
}
|
||||
@@ -557,17 +557,17 @@ public:
|
||||
m_project = m_helper.createProject(QLatin1String("testProject"));
|
||||
const CppTools::ProjectInfo projectInfo = createProjectInfo(m_project,
|
||||
m_projectFiles,
|
||||
m_projectDefines);
|
||||
m_projectMacros);
|
||||
const QSet<QString> filesIndexedAfterLoading = m_helper.updateProjectInfo(projectInfo);
|
||||
return m_projectFiles.size() == filesIndexedAfterLoading.size();
|
||||
}
|
||||
|
||||
bool updateProject(const QString &updatedProjectDefines)
|
||||
bool updateProject(const ProjectExplorer::Macros &updatedProjectMacros)
|
||||
{
|
||||
QTC_ASSERT(m_project, return false);
|
||||
const CppTools::ProjectInfo updatedProjectInfo = createProjectInfo(m_project,
|
||||
m_projectFiles,
|
||||
updatedProjectDefines);
|
||||
updatedProjectMacros);
|
||||
return updateProjectInfo(updatedProjectInfo);
|
||||
|
||||
}
|
||||
@@ -581,7 +581,7 @@ private:
|
||||
|
||||
ProjectExplorer::Project *m_project;
|
||||
QStringList m_projectFiles;
|
||||
QString m_projectDefines;
|
||||
ProjectExplorer::Macros m_projectMacros;
|
||||
CppTools::Tests::ModelManagerTestHelper m_helper;
|
||||
};
|
||||
|
||||
@@ -865,8 +865,7 @@ void ClangCodeCompletionTest::testCompleteProjectDependingCode()
|
||||
const TestDocument testDocument("completionWithProject.cpp");
|
||||
QVERIFY(testDocument.isCreatedAndHasValidCursorPosition());
|
||||
|
||||
ProjectLoader projectLoader(QStringList(testDocument.filePath),
|
||||
_("#define PROJECT_CONFIGURATION_1\n"));
|
||||
ProjectLoader projectLoader(QStringList(testDocument.filePath), {{"PROJECT_CONFIGURATION_1"}});
|
||||
QVERIFY(projectLoader.load());
|
||||
|
||||
OpenEditorAtCursorPosition openEditor(testDocument);
|
||||
@@ -891,7 +890,7 @@ void ClangCodeCompletionTest::testCompleteProjectDependingCodeAfterChangingProje
|
||||
{
|
||||
// Check completion with project configuration 1
|
||||
ProjectLoader projectLoader(QStringList(testDocument.filePath),
|
||||
_("#define PROJECT_CONFIGURATION_1\n"),
|
||||
{{"PROJECT_CONFIGURATION_1"}},
|
||||
/* testOnlyForCleanedProjects= */ true);
|
||||
QVERIFY(projectLoader.load());
|
||||
openEditor.waitUntilProjectPartChanged(QLatin1String("myproject.project"));
|
||||
@@ -902,7 +901,7 @@ void ClangCodeCompletionTest::testCompleteProjectDependingCodeAfterChangingProje
|
||||
QVERIFY(!hasItem(proposal, "projectConfiguration2"));
|
||||
|
||||
// Check completion with project configuration 2
|
||||
QVERIFY(projectLoader.updateProject(_("#define PROJECT_CONFIGURATION_2\n")));
|
||||
QVERIFY(projectLoader.updateProject({{"PROJECT_CONFIGURATION_2"}}));
|
||||
proposal = completionResults(openEditor.editor());
|
||||
|
||||
QVERIFY(!hasItem(proposal, "projectConfiguration1"));
|
||||
|
@@ -224,8 +224,8 @@ public:
|
||||
optionsBuilder.addDefineToAvoidIncludingGccOrMinGwIntrinsics();
|
||||
const Core::Id type = projectPart.toolchainType;
|
||||
if (type != ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID)
|
||||
optionsBuilder.addDefines(projectPart.toolchainDefines);
|
||||
optionsBuilder.addDefines(projectPart.projectDefines);
|
||||
optionsBuilder.addMacros(projectPart.toolChainMacros);
|
||||
optionsBuilder.addMacros(projectPart.projectMacros);
|
||||
optionsBuilder.undefineClangVersionMacrosForMsvc();
|
||||
optionsBuilder.undefineCppLanguageFeatureMacrosForMsvc2015();
|
||||
optionsBuilder.addHeaderPathOptions();
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/stringutils.h>
|
||||
#include <utils/algorithm.h>
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
#include <projectexplorer/projectnodes.h>
|
||||
|
||||
#include <QLoggingCategory>
|
||||
@@ -71,8 +72,9 @@ void CMakeCbpParser::sortFiles()
|
||||
qCDebug(log) << "# Pre Dump #";
|
||||
qCDebug(log) << "###############";
|
||||
foreach (const CMakeBuildTarget &target, m_buildTargets)
|
||||
qCDebug(log) << target.title << target.sourceDirectory <<
|
||||
target.includeFiles << target.defines << target.files << "\n";
|
||||
qCDebug(log) << target.title << target.sourceDirectory << target.includeFiles
|
||||
<< ProjectExplorer::Macro::toByteArray(target.macros)
|
||||
<< target.files << "\n";
|
||||
|
||||
// find a good build target to fall back
|
||||
int fallbackIndex = 0;
|
||||
@@ -153,7 +155,9 @@ void CMakeCbpParser::sortFiles()
|
||||
qCDebug(log) << "# After Dump #";
|
||||
qCDebug(log) << "###############";
|
||||
foreach (const CMakeBuildTarget &target, m_buildTargets)
|
||||
qCDebug(log) << target.title << target.sourceDirectory << target.includeFiles << target.defines << target.files << "\n";
|
||||
qCDebug(log) << target.title << target.sourceDirectory << target.includeFiles
|
||||
<< ProjectExplorer::Macro::toByteArray(target.macros)
|
||||
<< target.files << "\n";
|
||||
}
|
||||
|
||||
bool CMakeCbpParser::parseCbpFile(CMakeTool::PathMapper mapper, const FileName &fileName,
|
||||
@@ -397,12 +401,8 @@ void CMakeCbpParser::parseAdd()
|
||||
m_buildTarget.compilerOptions.append(compilerOption);
|
||||
int macroNameIndex = compilerOption.indexOf("-D") + 2;
|
||||
if (macroNameIndex != 1) {
|
||||
int assignIndex = compilerOption.indexOf('=', macroNameIndex);
|
||||
if (assignIndex != -1)
|
||||
compilerOption[assignIndex] = ' ';
|
||||
m_buildTarget.defines.append("#define ");
|
||||
m_buildTarget.defines.append(compilerOption.mid(macroNameIndex).toUtf8());
|
||||
m_buildTarget.defines.append('\n');
|
||||
const QString keyValue = compilerOption.mid(macroNameIndex);
|
||||
m_buildTarget.macros.append(ProjectExplorer::Macro::fromKeyValue(keyValue));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -559,7 +559,7 @@ void CMakeBuildTarget::clear()
|
||||
targetType = UtilityType;
|
||||
includeFiles.clear();
|
||||
compilerOptions.clear();
|
||||
defines.clear();
|
||||
macros.clear();
|
||||
files.clear();
|
||||
}
|
||||
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include "treescanner.h"
|
||||
|
||||
#include <projectexplorer/extracompiler.h>
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
#include <projectexplorer/project.h>
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
@@ -72,7 +73,7 @@ public:
|
||||
// code model
|
||||
QList<Utils::FileName> includeFiles;
|
||||
QStringList compilerOptions;
|
||||
QByteArray defines;
|
||||
ProjectExplorer::Macros macros;
|
||||
QList<Utils::FileName> files;
|
||||
|
||||
void clear();
|
||||
|
@@ -45,6 +45,8 @@
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/qtcprocess.h>
|
||||
|
||||
#include <QVector>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Utils;
|
||||
|
||||
@@ -325,14 +327,6 @@ void ServerModeReader::updateCodeModel(CppTools::RawProjectParts &rpps)
|
||||
int counter = 0;
|
||||
for (const FileGroup *fg : Utils::asConst(m_fileGroups)) {
|
||||
++counter;
|
||||
const QString defineArg
|
||||
= transform(fg->defines, [](const QString &s) -> QString {
|
||||
QString result = QString::fromLatin1("#define ") + s;
|
||||
int assignIndex = result.indexOf('=');
|
||||
if (assignIndex != -1)
|
||||
result[assignIndex] = ' ';
|
||||
return result;
|
||||
}).join('\n');
|
||||
const QStringList flags = QtcProcess::splitArgs(fg->compileFlags);
|
||||
const QStringList includes = transform(fg->includePaths, [](const IncludePath *ip) { return ip->path.toString(); });
|
||||
|
||||
@@ -340,7 +334,7 @@ void ServerModeReader::updateCodeModel(CppTools::RawProjectParts &rpps)
|
||||
rpp.setProjectFileLocation(fg->target->sourceDirectory.toString() + "/CMakeLists.txt");
|
||||
rpp.setBuildSystemTarget(fg->target->name);
|
||||
rpp.setDisplayName(fg->target->name + QString::number(counter));
|
||||
rpp.setDefines(defineArg.toUtf8());
|
||||
rpp.setMacros(fg->macros);
|
||||
rpp.setIncludePaths(includes);
|
||||
|
||||
CppTools::RawProjectPartFlags cProjectFlags;
|
||||
@@ -523,7 +517,9 @@ ServerModeReader::FileGroup *ServerModeReader::extractFileGroupData(const QVaria
|
||||
auto fileGroup = new FileGroup;
|
||||
fileGroup->target = t;
|
||||
fileGroup->compileFlags = data.value("compileFlags").toString();
|
||||
fileGroup->defines = data.value("defines").toStringList();
|
||||
fileGroup->macros = Utils::transform<QVector>(data.value("defines").toStringList(), [](const QString &s) {
|
||||
return ProjectExplorer::Macro::fromKeyValue(s);
|
||||
});
|
||||
fileGroup->includePaths = transform(data.value("includePath").toList(),
|
||||
[](const QVariant &i) -> IncludePath* {
|
||||
const QVariantMap iData = i.toMap();
|
||||
@@ -662,7 +658,7 @@ void ServerModeReader::fixTarget(ServerModeReader::Target *target) const
|
||||
|
||||
for (const FileGroup *group : Utils::asConst(target->fileGroups)) {
|
||||
if (group->includePaths.isEmpty() && group->compileFlags.isEmpty()
|
||||
&& group->defines.isEmpty())
|
||||
&& group->macros.isEmpty())
|
||||
continue;
|
||||
|
||||
const FileGroup *fallback = languageFallbacks.value(group->language);
|
||||
@@ -688,13 +684,13 @@ void ServerModeReader::fixTarget(ServerModeReader::Target *target) const
|
||||
(*it)->language = fallback->language.isEmpty() ? "CXX" : fallback->language;
|
||||
|
||||
if (*it == fallback
|
||||
|| !(*it)->includePaths.isEmpty() || !(*it)->defines.isEmpty()
|
||||
|| !(*it)->includePaths.isEmpty() || !(*it)->macros.isEmpty()
|
||||
|| !(*it)->compileFlags.isEmpty())
|
||||
continue;
|
||||
|
||||
for (const IncludePath *ip : fallback->includePaths)
|
||||
(*it)->includePaths.append(new IncludePath(*ip));
|
||||
(*it)->defines = fallback->defines;
|
||||
(*it)->macros = fallback->macros;
|
||||
(*it)->compileFlags = fallback->compileFlags;
|
||||
}
|
||||
}
|
||||
|
@@ -86,7 +86,7 @@ private:
|
||||
|
||||
Target *target = nullptr;
|
||||
QString compileFlags;
|
||||
QStringList defines;
|
||||
ProjectExplorer::Macros macros;
|
||||
QList<IncludePath *> includePaths;
|
||||
QString language;
|
||||
QList<Utils::FileName> sources;
|
||||
|
@@ -384,7 +384,7 @@ void TeaLeafReader::updateCodeModel(CppTools::RawProjectParts &rpps)
|
||||
cxxProjectFlags.commandLineFlags = cxxflags;
|
||||
rpp.setFlagsForCxx(cxxProjectFlags);
|
||||
|
||||
rpp.setDefines(cbt.defines);
|
||||
rpp.setMacros(cbt.macros);
|
||||
rpp.setDisplayName(cbt.title);
|
||||
rpp.setFiles(transform(cbt.files, [](const FileName &fn) { return fn.toString(); }));
|
||||
|
||||
|
@@ -35,6 +35,7 @@
|
||||
#include <cpptools/cppmodelmanager.h>
|
||||
#include <cpptools/cpptoolsbridge.h>
|
||||
#include <cpptools/cppworkingcopy.h>
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
#include <projectexplorer/project.h>
|
||||
|
||||
#include <cplusplus/CppDocument.h>
|
||||
@@ -49,6 +50,7 @@
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
using namespace CPlusPlus;
|
||||
using namespace CppTools;
|
||||
@@ -756,7 +758,7 @@ class MacrosModel : public QAbstractListModel
|
||||
Q_OBJECT
|
||||
public:
|
||||
MacrosModel(QObject *parent);
|
||||
void configure(const QList<Macro> ¯os);
|
||||
void configure(const QList<CPlusPlus::Macro> ¯os);
|
||||
void clear();
|
||||
|
||||
enum Columns { LineNumberColumn, MacroColumn, ColumnCount };
|
||||
@@ -767,14 +769,14 @@ public:
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
|
||||
|
||||
private:
|
||||
QList<Macro> m_macros;
|
||||
QList<CPlusPlus::Macro> m_macros;
|
||||
};
|
||||
|
||||
MacrosModel::MacrosModel(QObject *parent) : QAbstractListModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void MacrosModel::configure(const QList<Macro> ¯os)
|
||||
void MacrosModel::configure(const QList<CPlusPlus::Macro> ¯os)
|
||||
{
|
||||
emit layoutAboutToBeChanged();
|
||||
m_macros = macros;
|
||||
@@ -802,7 +804,7 @@ QVariant MacrosModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
const int column = index.column();
|
||||
if (role == Qt::DisplayRole || (role == Qt::ToolTipRole && column == MacroColumn)) {
|
||||
const Macro macro = m_macros.at(index.row());
|
||||
const CPlusPlus::Macro macro = m_macros.at(index.row());
|
||||
if (column == LineNumberColumn)
|
||||
return macro.line();
|
||||
else if (column == MacroColumn)
|
||||
@@ -1614,7 +1616,8 @@ void CppCodeModelInspectorDialog::refresh()
|
||||
}
|
||||
|
||||
// Merged entities
|
||||
dumper.dumpMergedEntities(cmmi->headerPaths(), cmmi->definedMacros());
|
||||
dumper.dumpMergedEntities(cmmi->headerPaths(),
|
||||
ProjectExplorer::Macro::toByteArray(cmmi->definedMacros()));
|
||||
}
|
||||
|
||||
enum DocumentTabs {
|
||||
@@ -1758,6 +1761,15 @@ void CppCodeModelInspectorDialog::clearProjectPartData()
|
||||
partTabName(ProjectPartPrecompiledHeadersTab));
|
||||
}
|
||||
|
||||
static int defineCount(const ProjectExplorer::Macros ¯os)
|
||||
{
|
||||
using ProjectExplorer::Macro;
|
||||
return int(std::count_if(
|
||||
macros.begin(),
|
||||
macros.end(),
|
||||
[](const Macro ¯o) { return macro.type == ProjectExplorer::MacroType::Define; }));
|
||||
}
|
||||
|
||||
void CppCodeModelInspectorDialog::updateProjectPartData(const ProjectPart::Ptr &part)
|
||||
{
|
||||
QTC_ASSERT(part, return);
|
||||
@@ -1802,16 +1814,10 @@ void CppCodeModelInspectorDialog::updateProjectPartData(const ProjectPart::Ptr &
|
||||
m_ui->projectPartTab->setTabText(ProjectPartFilesTab,
|
||||
partTabName(ProjectPartFilesTab, part->files.size()));
|
||||
|
||||
// Defines
|
||||
const QList<QByteArray> defineLines = part->toolchainDefines.split('\n')
|
||||
+ part->projectDefines.split('\n');
|
||||
int numberOfDefines = 0;
|
||||
foreach (const QByteArray &line, defineLines) {
|
||||
if (line.startsWith("#define "))
|
||||
++numberOfDefines;
|
||||
}
|
||||
m_ui->partToolchainDefinesEdit->setPlainText(QString::fromUtf8(part->toolchainDefines));
|
||||
m_ui->partProjectDefinesEdit->setPlainText(QString::fromUtf8(part->projectDefines));
|
||||
int numberOfDefines = defineCount(part->toolChainMacros) + defineCount(part->projectMacros);
|
||||
|
||||
m_ui->partToolchainDefinesEdit->setPlainText(QString::fromUtf8(ProjectExplorer::Macro::toByteArray(part->toolChainMacros)));
|
||||
m_ui->partProjectDefinesEdit->setPlainText(QString::fromUtf8(ProjectExplorer::Macro::toByteArray(part->projectMacros)));
|
||||
m_ui->projectPartTab->setTabText(ProjectPartDefinesTab,
|
||||
partTabName(ProjectPartDefinesTab, numberOfDefines));
|
||||
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include "builtineditordocumentparser.h"
|
||||
#include "cppsourceprocessor.h"
|
||||
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
#include <projectexplorer/projectexplorerconstants.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
@@ -91,9 +92,9 @@ void BuiltinEditorDocumentParser::updateImpl(const QFutureInterface<void> &futur
|
||||
}
|
||||
|
||||
if (const ProjectPart::Ptr part = baseState.projectPartInfo.projectPart) {
|
||||
configFile += part->toolchainDefines;
|
||||
configFile += ProjectExplorer::Macro::toByteArray(part->toolChainMacros);
|
||||
configFile += overwrittenToolchainDefines(*part.data());
|
||||
configFile += part->projectDefines;
|
||||
configFile += ProjectExplorer::Macro::toByteArray(part->projectMacros);
|
||||
if (!part->projectConfigFile.isEmpty())
|
||||
configFile += ProjectPart::readProjectConfigFile(part);
|
||||
headerPaths = part->headerPaths;
|
||||
|
@@ -48,44 +48,9 @@ void CompilerOptionsBuilder::add(const QString &option)
|
||||
m_options.append(option);
|
||||
}
|
||||
|
||||
struct Macro {
|
||||
static Macro fromDefineDirective(const QByteArray &defineDirective);
|
||||
QByteArray toDefineOption(const QByteArray &option) const;
|
||||
|
||||
QByteArray name;
|
||||
QByteArray value;
|
||||
};
|
||||
|
||||
Macro Macro::fromDefineDirective(const QByteArray &defineDirective)
|
||||
void CompilerOptionsBuilder::addDefine(const ProjectExplorer::Macro ¯o)
|
||||
{
|
||||
const QByteArray str = defineDirective.mid(8);
|
||||
const int spaceIdx = str.indexOf(' ');
|
||||
const bool hasValue = spaceIdx != -1;
|
||||
|
||||
Macro macro;
|
||||
macro.name = str.left(hasValue ? spaceIdx : str.size());
|
||||
if (hasValue)
|
||||
macro.value = str.mid(spaceIdx + 1);
|
||||
|
||||
return macro;
|
||||
}
|
||||
|
||||
QByteArray Macro::toDefineOption(const QByteArray &option) const
|
||||
{
|
||||
QByteArray result;
|
||||
|
||||
result.append(option);
|
||||
result.append(name);
|
||||
result.append('=');
|
||||
if (!value.isEmpty())
|
||||
result.append(value);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void CompilerOptionsBuilder::addDefine(const QByteArray &defineDirective)
|
||||
{
|
||||
m_options.append(defineDirectiveToDefineOption(defineDirective));
|
||||
m_options.append(defineDirectiveToDefineOption(macro));
|
||||
}
|
||||
|
||||
void CompilerOptionsBuilder::addWordWidth()
|
||||
@@ -162,19 +127,19 @@ void CompilerOptionsBuilder::addPrecompiledHeaderOptions(PchUsage pchUsage)
|
||||
|
||||
void CompilerOptionsBuilder::addToolchainAndProjectDefines()
|
||||
{
|
||||
addDefines(m_projectPart.toolchainDefines);
|
||||
addDefines(m_projectPart.projectDefines);
|
||||
addMacros(m_projectPart.toolChainMacros);
|
||||
addMacros(m_projectPart.projectMacros);
|
||||
}
|
||||
|
||||
void CompilerOptionsBuilder::addDefines(const QByteArray &defineDirectives)
|
||||
void CompilerOptionsBuilder::addMacros(const ProjectExplorer::Macros ¯os)
|
||||
{
|
||||
QStringList result;
|
||||
|
||||
foreach (QByteArray def, defineDirectives.split('\n')) {
|
||||
if (def.isEmpty() || excludeDefineDirective(def))
|
||||
for (const ProjectExplorer::Macro ¯o : macros) {
|
||||
if (excludeDefineDirective(macro))
|
||||
continue;
|
||||
|
||||
const QString defineOption = defineDirectiveToDefineOption(def);
|
||||
const QString defineOption = defineDirectiveToDefineOption(macro);
|
||||
if (!result.contains(defineOption))
|
||||
result.append(defineOption);
|
||||
}
|
||||
@@ -303,8 +268,8 @@ void CompilerOptionsBuilder::addDefineToAvoidIncludingGccOrMinGwIntrinsics()
|
||||
const Core::Id type = m_projectPart.toolchainType;
|
||||
if (type == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID
|
||||
|| type == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID) {
|
||||
addDefine("#define _X86INTRIN_H_INCLUDED");
|
||||
addDefine("#define BOOST_UUID_NO_SIMD");
|
||||
addDefine({"_X86INTRIN_H_INCLUDED"});
|
||||
addDefine({"BOOST_UUID_NO_SIMD"});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,14 +280,10 @@ static QByteArray toMsCompatibilityVersionFormat(const QByteArray &mscFullVer)
|
||||
+ mscFullVer.mid(2, 2);
|
||||
}
|
||||
|
||||
static QByteArray msCompatibilityVersionFromDefines(const QByteArray &defineDirectives)
|
||||
static QByteArray msCompatibilityVersionFromDefines(const ProjectExplorer::Macros ¯os)
|
||||
{
|
||||
foreach (QByteArray defineDirective, defineDirectives.split('\n')) {
|
||||
if (defineDirective.isEmpty())
|
||||
continue;
|
||||
|
||||
const Macro macro = Macro::fromDefineDirective(defineDirective);
|
||||
if (macro.name == "_MSC_FULL_VER")
|
||||
for (const ProjectExplorer::Macro ¯o : macros) {
|
||||
if (macro.key == "_MSC_FULL_VER")
|
||||
return toMsCompatibilityVersionFormat(macro.value);
|
||||
}
|
||||
|
||||
@@ -332,8 +293,8 @@ static QByteArray msCompatibilityVersionFromDefines(const QByteArray &defineDire
|
||||
void CompilerOptionsBuilder::addMsvcCompatibilityVersion()
|
||||
{
|
||||
if (m_projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID) {
|
||||
const QByteArray defines = m_projectPart.toolchainDefines + m_projectPart.projectDefines;
|
||||
const QByteArray msvcVersion = msCompatibilityVersionFromDefines(defines);
|
||||
const ProjectExplorer::Macros macros = m_projectPart.toolChainMacros + m_projectPart.projectMacros;
|
||||
const QByteArray msvcVersion = msCompatibilityVersionFromDefines(macros);
|
||||
|
||||
if (!msvcVersion.isEmpty()) {
|
||||
const QString option = QLatin1String("-fms-compatibility-version=")
|
||||
@@ -398,7 +359,7 @@ void CompilerOptionsBuilder::addDefineFloat128ForMingw()
|
||||
// CLANG-UPGRADE-CHECK: Workaround still needed?
|
||||
// https://llvm.org/bugs/show_bug.cgi?id=30685
|
||||
if (m_projectPart.toolchainType == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID)
|
||||
addDefine("#define __float128 short");
|
||||
addDefine({"__float128", "short", ProjectExplorer::MacroType::Define});
|
||||
}
|
||||
|
||||
QString CompilerOptionsBuilder::includeDirOption() const
|
||||
@@ -406,12 +367,25 @@ QString CompilerOptionsBuilder::includeDirOption() const
|
||||
return QLatin1String("-I");
|
||||
}
|
||||
|
||||
QString CompilerOptionsBuilder::defineDirectiveToDefineOption(const QByteArray &defineDirective)
|
||||
QByteArray CompilerOptionsBuilder::macroOption(const ProjectExplorer::Macro ¯o) const
|
||||
{
|
||||
const Macro macro = Macro::fromDefineDirective(defineDirective);
|
||||
const QByteArray option = macro.toDefineOption(defineOption().toLatin1());
|
||||
switch (macro.type) {
|
||||
case ProjectExplorer::MacroType::Define: return defineOption().toUtf8();
|
||||
case ProjectExplorer::MacroType::Undefine: return undefineOption().toUtf8();
|
||||
default: return QByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
return QString::fromLatin1(option);
|
||||
QByteArray CompilerOptionsBuilder::toDefineOption(const ProjectExplorer::Macro ¯o) const
|
||||
{
|
||||
return macro.toKeyValue(macroOption(macro));
|
||||
}
|
||||
|
||||
QString CompilerOptionsBuilder::defineDirectiveToDefineOption(const ProjectExplorer::Macro ¯o) const
|
||||
{
|
||||
const QByteArray option = toDefineOption(macro);
|
||||
|
||||
return QString::fromUtf8(option);
|
||||
}
|
||||
|
||||
QString CompilerOptionsBuilder::defineOption() const
|
||||
@@ -435,11 +409,11 @@ static bool isGccOrMinGwToolchain(const Core::Id &toolchainType)
|
||||
|| toolchainType == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID;
|
||||
}
|
||||
|
||||
bool CompilerOptionsBuilder::excludeDefineDirective(const QByteArray &defineDirective) const
|
||||
bool CompilerOptionsBuilder::excludeDefineDirective(const ProjectExplorer::Macro ¯o) const
|
||||
{
|
||||
// This is a quick fix for QTCREATORBUG-11501.
|
||||
// TODO: do a proper fix, see QTCREATORBUG-11709.
|
||||
if (defineDirective.startsWith("#define __cplusplus"))
|
||||
if (macro.key == "__cplusplus")
|
||||
return true;
|
||||
|
||||
// gcc 4.9 has:
|
||||
@@ -449,7 +423,7 @@ bool CompilerOptionsBuilder::excludeDefineDirective(const QByteArray &defineDire
|
||||
// override clang's own (non-macro, it seems) definitions of the symbols on the left-hand
|
||||
// side.
|
||||
if (isGccOrMinGwToolchain(m_projectPart.toolchainType)
|
||||
&& defineDirective.contains("has_include")) {
|
||||
&& macro.key.contains("has_include")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -459,14 +433,14 @@ bool CompilerOptionsBuilder::excludeDefineDirective(const QByteArray &defineDire
|
||||
// __builtin_va_arg_pack, which clang does not support (yet), so avoid
|
||||
// including those.
|
||||
if (m_projectPart.toolchainType == ProjectExplorer::Constants::GCC_TOOLCHAIN_TYPEID
|
||||
&& defineDirective.startsWith("#define _FORTIFY_SOURCE")) {
|
||||
&& macro.key == "_FORTIFY_SOURCE") {
|
||||
return true;
|
||||
}
|
||||
|
||||
// MinGW 6 supports some fancy asm output flags and uses them in an
|
||||
// intrinsics header pulled in by windows.h. Clang does not know them.
|
||||
if (m_projectPart.toolchainType == ProjectExplorer::Constants::MINGW_TOOLCHAIN_TYPEID
|
||||
&& defineDirective.startsWith("#define __GCC_ASM_FLAG_OUTPUTS__")) {
|
||||
&& macro.key == "__GCC_ASM_FLAG_OUTPUTS__") {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -46,7 +46,7 @@ public:
|
||||
|
||||
// Add custom options
|
||||
void add(const QString &option);
|
||||
void addDefine(const QByteArray &defineDirective);
|
||||
void addDefine(const ProjectExplorer::Macro &marco);
|
||||
|
||||
// Add options based on project part
|
||||
void addWordWidth();
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
void addHeaderPathOptions();
|
||||
void addPrecompiledHeaderOptions(PchUsage pchUsage);
|
||||
void addToolchainAndProjectDefines();
|
||||
void addDefines(const QByteArray &defineDirectives);
|
||||
void addMacros(const ProjectExplorer::Macros ¯os);
|
||||
virtual void addLanguageOption(ProjectFile::Kind fileKind);
|
||||
virtual void addOptionsForLanguage(bool checkForBorlandExtensions = true);
|
||||
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
void addDefineFloat128ForMingw();
|
||||
|
||||
protected:
|
||||
virtual bool excludeDefineDirective(const QByteArray &defineDirective) const;
|
||||
virtual bool excludeDefineDirective(const ProjectExplorer::Macro ¯o) const;
|
||||
virtual bool excludeHeaderPath(const QString &headerPath) const;
|
||||
|
||||
virtual QString defineOption() const;
|
||||
@@ -78,7 +78,9 @@ protected:
|
||||
const ProjectPart m_projectPart;
|
||||
|
||||
private:
|
||||
QString defineDirectiveToDefineOption(const QByteArray &defineDirective);
|
||||
QByteArray macroOption(const ProjectExplorer::Macro ¯o) const;
|
||||
QByteArray toDefineOption(const ProjectExplorer::Macro ¯o) const;
|
||||
QString defineDirectiveToDefineOption(const ProjectExplorer::Macro &marco) const;
|
||||
|
||||
QStringList m_options;
|
||||
};
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include <app/app_version.h>
|
||||
#include <coreplugin/icore.h>
|
||||
#include <cpptools/cppprojectfile.h>
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/temporarydirectory.h>
|
||||
@@ -495,15 +496,17 @@ void Dumper::dumpProjectInfos( const QList<ProjectInfo> &projectInfos)
|
||||
}
|
||||
}
|
||||
|
||||
if (!part->toolchainDefines.isEmpty()) {
|
||||
if (!part->toolChainMacros.isEmpty()) {
|
||||
m_out << i3 << "Toolchain Defines:{{{4\n";
|
||||
const QList<QByteArray> defineLines = part->toolchainDefines.split('\n');
|
||||
const QList<QByteArray> defineLines =
|
||||
ProjectExplorer::Macro::toByteArray(part->toolChainMacros).split('\n');
|
||||
foreach (const QByteArray &defineLine, defineLines)
|
||||
m_out << i4 << defineLine << "\n";
|
||||
}
|
||||
if (!part->projectDefines.isEmpty()) {
|
||||
if (!part->projectMacros.isEmpty()) {
|
||||
m_out << i3 << "Project Defines:{{{4\n";
|
||||
const QList<QByteArray> defineLines = part->projectDefines.split('\n');
|
||||
const QList<QByteArray> defineLines =
|
||||
ProjectExplorer::Macro::toByteArray(part->projectMacros).split('\n');
|
||||
foreach (const QByteArray &defineLine, defineLines)
|
||||
m_out << i4 << defineLine << "\n";
|
||||
}
|
||||
|
@@ -1902,7 +1902,7 @@ void InternalCppCompletionAssistProcessor::addMacros_helper(const Snapshot &snap
|
||||
foreach (const Document::Include &i, doc->resolvedIncludes())
|
||||
addMacros_helper(snapshot, i.resolvedFileName(), processed, definedMacros);
|
||||
|
||||
foreach (const Macro ¯o, doc->definedMacros()) {
|
||||
foreach (const CPlusPlus::Macro ¯o, doc->definedMacros()) {
|
||||
const QString macroName = macro.nameToQString();
|
||||
if (!macro.isHidden())
|
||||
definedMacros->insert(macroName);
|
||||
|
@@ -607,13 +607,13 @@ class FindMacroUsesInFile: public std::unary_function<QString, QList<Usage> >
|
||||
{
|
||||
const WorkingCopy workingCopy;
|
||||
const Snapshot snapshot;
|
||||
const Macro ¯o;
|
||||
const CPlusPlus::Macro ¯o;
|
||||
QFutureInterface<Usage> *future;
|
||||
|
||||
public:
|
||||
FindMacroUsesInFile(const WorkingCopy &workingCopy,
|
||||
const Snapshot snapshot,
|
||||
const Macro ¯o,
|
||||
const CPlusPlus::Macro ¯o,
|
||||
QFutureInterface<Usage> *future)
|
||||
: workingCopy(workingCopy), snapshot(snapshot), macro(macro), future(future)
|
||||
{ }
|
||||
@@ -632,7 +632,7 @@ restart_search:
|
||||
|
||||
usages.clear();
|
||||
foreach (const Document::MacroUse &use, doc->macroUses()) {
|
||||
const Macro &useMacro = use.macro();
|
||||
const CPlusPlus::Macro &useMacro = use.macro();
|
||||
|
||||
if (useMacro.fileName() == macro.fileName()) { // Check if this is a match, but possibly against an outdated document.
|
||||
if (source.isEmpty())
|
||||
@@ -687,7 +687,7 @@ restart_search:
|
||||
static void findMacroUses_helper(QFutureInterface<Usage> &future,
|
||||
const WorkingCopy workingCopy,
|
||||
const Snapshot snapshot,
|
||||
const Macro macro)
|
||||
const CPlusPlus::Macro macro)
|
||||
{
|
||||
const Utils::FileName sourceFile = Utils::FileName::fromString(macro.fileName());
|
||||
Utils::FileNameList files{sourceFile};
|
||||
@@ -704,12 +704,13 @@ static void findMacroUses_helper(QFutureInterface<Usage> &future,
|
||||
future.setProgressValue(files.size());
|
||||
}
|
||||
|
||||
void CppFindReferences::findMacroUses(const Macro ¯o)
|
||||
void CppFindReferences::findMacroUses(const CPlusPlus::Macro ¯o)
|
||||
{
|
||||
findMacroUses(macro, QString(), false);
|
||||
}
|
||||
|
||||
void CppFindReferences::findMacroUses(const Macro ¯o, const QString &replacement, bool replace)
|
||||
void CppFindReferences::findMacroUses(const CPlusPlus::Macro ¯o, const QString &replacement,
|
||||
bool replace)
|
||||
{
|
||||
SearchResult *search = SearchResultWindow::instance()->startNewSearch(
|
||||
tr("C++ Macro Usages:"),
|
||||
@@ -753,7 +754,7 @@ void CppFindReferences::findMacroUses(const Macro ¯o, const QString &replace
|
||||
connect(progress, &FutureProgress::clicked, search, &SearchResult::popup);
|
||||
}
|
||||
|
||||
void CppFindReferences::renameMacroUses(const Macro ¯o, const QString &replacement)
|
||||
void CppFindReferences::renameMacroUses(const CPlusPlus::Macro ¯o, const QString &replacement)
|
||||
{
|
||||
const QString textToReplace = replacement.isEmpty() ? macro.nameToQString() : replacement;
|
||||
findMacroUses(macro, textToReplace, true);
|
||||
|
@@ -47,6 +47,7 @@
|
||||
#include <texteditor/textdocument.h>
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
#include <projectexplorer/session.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <utils/fileutils.h>
|
||||
@@ -138,7 +139,7 @@ public:
|
||||
bool m_dirty;
|
||||
QStringList m_projectFiles;
|
||||
ProjectPartHeaderPaths m_headerPaths;
|
||||
QByteArray m_definedMacros;
|
||||
ProjectExplorer::Macros m_definedMacros;
|
||||
|
||||
// Editor integration
|
||||
mutable QMutex m_cppEditorDocumentsMutex;
|
||||
@@ -446,35 +447,31 @@ ProjectPartHeaderPaths CppModelManager::internalHeaderPaths() const
|
||||
return headerPaths;
|
||||
}
|
||||
|
||||
static void addUnique(const QList<QByteArray> &defs, QByteArray *macros, QSet<QByteArray> *alreadyIn)
|
||||
static void addUnique(const ProjectExplorer::Macros &newMacros,
|
||||
ProjectExplorer::Macros ¯os,
|
||||
QSet<ProjectExplorer::Macro> &alreadyIn)
|
||||
{
|
||||
Q_ASSERT(macros);
|
||||
Q_ASSERT(alreadyIn);
|
||||
|
||||
foreach (const QByteArray &def, defs) {
|
||||
if (def.trimmed().isEmpty())
|
||||
continue;
|
||||
if (!alreadyIn->contains(def)) {
|
||||
macros->append(def);
|
||||
macros->append('\n');
|
||||
alreadyIn->insert(def);
|
||||
for (const ProjectExplorer::Macro ¯o : newMacros) {
|
||||
if (!alreadyIn.contains(macro)) {
|
||||
macros += macro;
|
||||
alreadyIn.insert(macro);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray CppModelManager::internalDefinedMacros() const
|
||||
ProjectExplorer::Macros CppModelManager::internalDefinedMacros() const
|
||||
{
|
||||
QByteArray macros;
|
||||
QSet<QByteArray> alreadyIn;
|
||||
ProjectExplorer::Macros macros;
|
||||
QSet<ProjectExplorer::Macro> alreadyIn;
|
||||
QMapIterator<ProjectExplorer::Project *, ProjectInfo> it(d->m_projectToProjectsInfo);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
const ProjectInfo pinfo = it.value();
|
||||
foreach (const ProjectPart::Ptr &part, pinfo.projectParts()) {
|
||||
addUnique(part->toolchainDefines.split('\n'), ¯os, &alreadyIn);
|
||||
addUnique(part->projectDefines.split('\n'), ¯os, &alreadyIn);
|
||||
for (const ProjectPart::Ptr &part : pinfo.projectParts()) {
|
||||
addUnique(part->toolChainMacros, macros, alreadyIn);
|
||||
addUnique(part->projectMacros, macros, alreadyIn);
|
||||
if (!part->projectConfigFile.isEmpty())
|
||||
macros += ProjectPart::readProjectConfigFile(part);
|
||||
macros += ProjectExplorer::Macro::toMacros(ProjectPart::readProjectConfigFile(part));
|
||||
}
|
||||
}
|
||||
return macros;
|
||||
@@ -491,7 +488,8 @@ void CppModelManager::dumpModelManagerConfiguration(const QString &logFileId)
|
||||
dumper.dumpProjectInfos(projectInfos());
|
||||
dumper.dumpSnapshot(globalSnapshot, globalSnapshotTitle, /*isGlobalSnapshot=*/ true);
|
||||
dumper.dumpWorkingCopy(workingCopy());
|
||||
dumper.dumpMergedEntities(headerPaths(), definedMacros());
|
||||
dumper.dumpMergedEntities(headerPaths(),
|
||||
ProjectExplorer:: Macro::toByteArray(definedMacros()));
|
||||
}
|
||||
|
||||
QSet<AbstractEditorSupport *> CppModelManager::abstractEditorSupports() const
|
||||
@@ -569,12 +567,12 @@ void CppModelManager::renameUsages(Symbol *symbol,
|
||||
d->m_findReferences->renameUsages(symbol, context, replacement);
|
||||
}
|
||||
|
||||
void CppModelManager::findMacroUsages(const Macro ¯o)
|
||||
void CppModelManager::findMacroUsages(const CPlusPlus::Macro ¯o)
|
||||
{
|
||||
d->m_findReferences->findMacroUses(macro);
|
||||
}
|
||||
|
||||
void CppModelManager::renameMacroUsages(const Macro ¯o, const QString &replacement)
|
||||
void CppModelManager::renameMacroUsages(const CPlusPlus::Macro ¯o, const QString &replacement)
|
||||
{
|
||||
d->m_findReferences->renameMacroUses(macro, replacement);
|
||||
}
|
||||
@@ -603,7 +601,7 @@ WorkingCopy CppModelManager::buildWorkingCopyList()
|
||||
|
||||
// Add the project configuration file
|
||||
QByteArray conf = codeModelConfiguration();
|
||||
conf += definedMacros();
|
||||
conf += ProjectExplorer::Macro::toByteArray(definedMacros());
|
||||
workingCopy.insert(configurationFileName(), conf);
|
||||
|
||||
return workingCopy;
|
||||
@@ -991,7 +989,7 @@ ProjectPart::Ptr CppModelManager::fallbackProjectPart()
|
||||
{
|
||||
ProjectPart::Ptr part(new ProjectPart);
|
||||
|
||||
part->projectDefines = definedMacros();
|
||||
part->projectMacros = definedMacros();
|
||||
part->headerPaths = headerPaths();
|
||||
|
||||
// Do not activate ObjectiveCExtensions since this will lead to the
|
||||
@@ -1270,7 +1268,7 @@ void CppModelManager::setHeaderPaths(const ProjectPartHeaderPaths &headerPaths)
|
||||
d->m_headerPaths = headerPaths;
|
||||
}
|
||||
|
||||
QByteArray CppModelManager::definedMacros()
|
||||
ProjectExplorer::Macros CppModelManager::definedMacros()
|
||||
{
|
||||
QMutexLocker locker(&d->m_projectMutex);
|
||||
ensureUpdated();
|
||||
|
@@ -163,7 +163,7 @@ public:
|
||||
// Use this *only* for auto tests
|
||||
void setHeaderPaths(const ProjectPartHeaderPaths &headerPaths);
|
||||
|
||||
QByteArray definedMacros();
|
||||
ProjectExplorer::Macros definedMacros();
|
||||
|
||||
void enableGarbageCollector(bool enable);
|
||||
|
||||
@@ -229,7 +229,7 @@ private:
|
||||
void ensureUpdated();
|
||||
QStringList internalProjectFiles() const;
|
||||
ProjectPartHeaderPaths internalHeaderPaths() const;
|
||||
QByteArray internalDefinedMacros() const;
|
||||
ProjectExplorer::Macros internalDefinedMacros() const;
|
||||
|
||||
void dumpModelManagerConfiguration(const QString &logFileId);
|
||||
|
||||
|
@@ -187,7 +187,7 @@ void CppToolsPlugin::test_modelmanager_paths_are_clean()
|
||||
|
||||
ProjectPart::Ptr part(new ProjectPart);
|
||||
part->qtVersion = ProjectPart::Qt5;
|
||||
part->projectDefines = QByteArray("#define OH_BEHAVE -1\n");
|
||||
part->projectMacros = {ProjectExplorer::Macro("OH_BEHAVE", "-1")};
|
||||
part->headerPaths = {HeaderPath(testDataDir.includeDir(false), HeaderPath::IncludePath),
|
||||
HeaderPath(testDataDir.frameworksDir(false), HeaderPath::FrameworkPath)};
|
||||
pi.appendProjectPart(part);
|
||||
@@ -219,7 +219,7 @@ void CppToolsPlugin::test_modelmanager_framework_headers()
|
||||
|
||||
ProjectPart::Ptr part(new ProjectPart);
|
||||
part->qtVersion = ProjectPart::Qt5;
|
||||
part->projectDefines = QByteArray("#define OH_BEHAVE -1\n");
|
||||
part->projectMacros = {{"OH_BEHAVE", "-1"}};
|
||||
part->headerPaths = {HeaderPath(testDataDir.includeDir(false), HeaderPath::IncludePath),
|
||||
HeaderPath(testDataDir.frameworksDir(false), HeaderPath::FrameworkPath)};
|
||||
const QString &source = testDataDir.fileFromSourcesDir(
|
||||
@@ -268,7 +268,7 @@ void CppToolsPlugin::test_modelmanager_refresh_also_includes_of_project_files()
|
||||
|
||||
ProjectPart::Ptr part(new ProjectPart);
|
||||
part->qtVersion = ProjectPart::Qt5;
|
||||
part->projectDefines = QByteArray("#define OH_BEHAVE -1\n");
|
||||
part->projectMacros = {{"OH_BEHAVE", "-1"}};
|
||||
part->headerPaths = {HeaderPath(testDataDir.includeDir(false), HeaderPath::IncludePath)};
|
||||
part->files.append(ProjectFile(testCpp, ProjectFile::CXXSource));
|
||||
pi.appendProjectPart(part);
|
||||
@@ -286,7 +286,7 @@ void CppToolsPlugin::test_modelmanager_refresh_also_includes_of_project_files()
|
||||
QVERIFY(macrosInHeaderBefore.first().name() == "test_modelmanager_refresh_h");
|
||||
|
||||
// Introduce a define that will enable another define once the document is reparsed.
|
||||
part->projectDefines = QByteArray("#define TEST_DEFINE 1\n");
|
||||
part->projectMacros = {{"TEST_DEFINE", "1"}};
|
||||
pi = ProjectInfo(project);
|
||||
pi.appendProjectPart(part);
|
||||
|
||||
@@ -334,13 +334,13 @@ void CppToolsPlugin::test_modelmanager_refresh_several_times()
|
||||
QSet<QString> refreshedFiles;
|
||||
CPlusPlus::Document::Ptr document;
|
||||
|
||||
QByteArray defines = "#define FIRST_DEFINE";
|
||||
ProjectExplorer::Macros macros = {{"FIRST_DEFINE"}};
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
pi = ProjectInfo(project);
|
||||
ProjectPart::Ptr part(new ProjectPart);
|
||||
// Simulate project configuration change by having different defines each time.
|
||||
defines += "\n#define ANOTHER_DEFINE";
|
||||
part->projectDefines = defines;
|
||||
macros += {"ANOTHER_DEFINE"};
|
||||
part->projectMacros = macros;
|
||||
part->qtVersion = ProjectPart::Qt5;
|
||||
part->files.append(ProjectFile(testHeader1, ProjectFile::CXXHeader));
|
||||
part->files.append(ProjectFile(testHeader2, ProjectFile::CXXHeader));
|
||||
@@ -762,7 +762,7 @@ void CppToolsPlugin::test_modelmanager_defines_per_project()
|
||||
part1->files.append(ProjectFile(main1File, ProjectFile::CXXSource));
|
||||
part1->files.append(ProjectFile(header, ProjectFile::CXXHeader));
|
||||
part1->qtVersion = ProjectPart::NoQt;
|
||||
part1->projectDefines = QByteArray("#define SUB1\n");
|
||||
part1->projectMacros = {{"SUB1"}};
|
||||
part1->headerPaths = {HeaderPath(testDataDirectory.includeDir(false), HeaderPath::IncludePath)};
|
||||
|
||||
ProjectPart::Ptr part2(new ProjectPart);
|
||||
@@ -770,7 +770,7 @@ void CppToolsPlugin::test_modelmanager_defines_per_project()
|
||||
part2->files.append(ProjectFile(main2File, ProjectFile::CXXSource));
|
||||
part2->files.append(ProjectFile(header, ProjectFile::CXXHeader));
|
||||
part2->qtVersion = ProjectPart::NoQt;
|
||||
part2->projectDefines = QByteArray("#define SUB2\n");
|
||||
part2->projectMacros = {{"SUB2"}};
|
||||
part2->headerPaths = {HeaderPath(testDataDirectory.includeDir(false), HeaderPath::IncludePath)};
|
||||
|
||||
ProjectInfo pi = ProjectInfo(project);
|
||||
|
@@ -143,7 +143,7 @@ private:
|
||||
if (!m_tcInfo.predefinedMacrosRunner)
|
||||
return; // No compiler set in kit.
|
||||
|
||||
m_projectPart.toolchainDefines = m_tcInfo.predefinedMacrosRunner(m_flags.commandLineFlags);
|
||||
m_projectPart.toolChainMacros = m_tcInfo.predefinedMacrosRunner(m_flags.commandLineFlags);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -187,7 +187,7 @@ static ProjectPart::Ptr projectPartFromRawProjectPart(const RawProjectPart &rawP
|
||||
part->callGroupId = rawProjectPart.callGroupId;
|
||||
part->buildSystemTarget = rawProjectPart.buildSystemTarget;
|
||||
part->qtVersion = rawProjectPart.qtVersion;
|
||||
part->projectDefines = rawProjectPart.projectDefines;
|
||||
part->projectMacros = rawProjectPart.projectMacros;
|
||||
part->headerPaths = rawProjectPart.headerPaths;
|
||||
part->precompiledHeaders = rawProjectPart.precompiledHeaders;
|
||||
part->selectedForBuilding = rawProjectPart.selectedForBuilding;
|
||||
|
@@ -81,9 +81,9 @@ void RawProjectPart::setQtVersion(ProjectPart::QtVersion qtVersion)
|
||||
this->qtVersion = qtVersion;
|
||||
}
|
||||
|
||||
void RawProjectPart::setDefines(const QByteArray &defines)
|
||||
void RawProjectPart::setMacros(const ProjectExplorer::Macros ¯os)
|
||||
{
|
||||
this->projectDefines = defines;
|
||||
this->projectMacros = macros;
|
||||
}
|
||||
|
||||
void RawProjectPart::setHeaderPaths(const ProjectPartHeaderPaths &headerPaths)
|
||||
|
@@ -67,7 +67,7 @@ public:
|
||||
|
||||
void setQtVersion(ProjectPart::QtVersion qtVersion);
|
||||
|
||||
void setDefines(const QByteArray &defines);
|
||||
void setMacros(const ProjectExplorer::Macros ¯os);
|
||||
void setHeaderPaths(const ProjectPartHeaderPaths &headerPaths);
|
||||
void setIncludePaths(const QStringList &includePaths);
|
||||
|
||||
@@ -88,7 +88,7 @@ public:
|
||||
QString buildSystemTarget;
|
||||
QStringList precompiledHeaders;
|
||||
ProjectPartHeaderPaths headerPaths;
|
||||
QByteArray projectDefines;
|
||||
ProjectExplorer::Macros projectMacros;
|
||||
ProjectPart::QtVersion qtVersion = ProjectPart::UnknownQt;
|
||||
bool selectedForBuilding = true;
|
||||
|
||||
|
@@ -62,11 +62,12 @@ static Q_LOGGING_CATEGORY(log, "qtc.cpptools.sourceprocessor")
|
||||
|
||||
namespace {
|
||||
|
||||
inline QByteArray generateFingerPrint(const QList<Macro> &definedMacros, const QByteArray &code)
|
||||
inline QByteArray generateFingerPrint(const QList<CPlusPlus::Macro> &definedMacros,
|
||||
const QByteArray &code)
|
||||
{
|
||||
QCryptographicHash hash(QCryptographicHash::Sha1);
|
||||
hash.addData(code);
|
||||
foreach (const Macro ¯o, definedMacros) {
|
||||
foreach (const CPlusPlus::Macro ¯o, definedMacros) {
|
||||
if (macro.isHidden()) {
|
||||
static const QByteArray undef("#undef ");
|
||||
hash.addData(undef);
|
||||
@@ -98,10 +99,10 @@ inline Message messageNoFileContents(Document::Ptr &document, const QString &fil
|
||||
return Message(Message::Warning, document->fileName(), line, /*column =*/ 0, text);
|
||||
}
|
||||
|
||||
inline const Macro revision(const WorkingCopy &workingCopy,
|
||||
const Macro ¯o)
|
||||
inline const CPlusPlus::Macro revision(const WorkingCopy &workingCopy,
|
||||
const CPlusPlus::Macro ¯o)
|
||||
{
|
||||
Macro newMacro(macro);
|
||||
CPlusPlus::Macro newMacro(macro);
|
||||
newMacro.setFileRevision(workingCopy.get(macro.fileName()).second);
|
||||
return newMacro;
|
||||
}
|
||||
@@ -316,7 +317,7 @@ QString CppSourceProcessor::resolveFile_helper(const QString &fileName,
|
||||
return QString();
|
||||
}
|
||||
|
||||
void CppSourceProcessor::macroAdded(const Macro ¯o)
|
||||
void CppSourceProcessor::macroAdded(const CPlusPlus::Macro ¯o)
|
||||
{
|
||||
if (!m_currentDoc)
|
||||
return;
|
||||
@@ -325,7 +326,7 @@ void CppSourceProcessor::macroAdded(const Macro ¯o)
|
||||
}
|
||||
|
||||
void CppSourceProcessor::passedMacroDefinitionCheck(unsigned bytesOffset, unsigned utf16charsOffset,
|
||||
unsigned line, const Macro ¯o)
|
||||
unsigned line, const CPlusPlus::Macro ¯o)
|
||||
{
|
||||
if (!m_currentDoc)
|
||||
return;
|
||||
@@ -347,7 +348,7 @@ void CppSourceProcessor::failedMacroDefinitionCheck(unsigned bytesOffset, unsign
|
||||
}
|
||||
|
||||
void CppSourceProcessor::notifyMacroReference(unsigned bytesOffset, unsigned utf16charOffset,
|
||||
unsigned line, const Macro ¯o)
|
||||
unsigned line, const CPlusPlus::Macro ¯o)
|
||||
{
|
||||
if (!m_currentDoc)
|
||||
return;
|
||||
@@ -359,7 +360,7 @@ void CppSourceProcessor::notifyMacroReference(unsigned bytesOffset, unsigned utf
|
||||
}
|
||||
|
||||
void CppSourceProcessor::startExpandingMacro(unsigned bytesOffset, unsigned utf16charOffset,
|
||||
unsigned line, const Macro ¯o,
|
||||
unsigned line, const CPlusPlus::Macro ¯o,
|
||||
const QVector<MacroArgumentReference> &actuals)
|
||||
{
|
||||
if (!m_currentDoc)
|
||||
@@ -371,7 +372,7 @@ void CppSourceProcessor::startExpandingMacro(unsigned bytesOffset, unsigned utf1
|
||||
line, actuals);
|
||||
}
|
||||
|
||||
void CppSourceProcessor::stopExpandingMacro(unsigned, const Macro &)
|
||||
void CppSourceProcessor::stopExpandingMacro(unsigned, const CPlusPlus::Macro &)
|
||||
{
|
||||
if (!m_currentDoc)
|
||||
return;
|
||||
|
@@ -1,11 +1,7 @@
|
||||
# Currently there are no tests for the project explorer plugin, but we include
|
||||
# headers from it that needs to have the export/import adapted for Windows.
|
||||
shared {
|
||||
DEFINES += CPPTOOLS_LIBRARY
|
||||
DEFINES += PROJECTEXPLORER_LIBRARY
|
||||
} else {
|
||||
DEFINES += CPPTOOLS_STATIC_LIBRARY
|
||||
DEFINES += PROJECTEXPLORER_STATIC_LIBRARY
|
||||
}
|
||||
|
||||
HEADERS += \
|
||||
|
@@ -160,13 +160,10 @@ void ProjectInfo::finish()
|
||||
m_sourceFiles.insert(file.path);
|
||||
|
||||
// Update defines
|
||||
m_defines.append(part->toolchainDefines);
|
||||
m_defines.append(part->projectDefines);
|
||||
if (!part->projectConfigFile.isEmpty()) {
|
||||
m_defines.append('\n');
|
||||
m_defines += ProjectPart::readProjectConfigFile(part);
|
||||
m_defines.append('\n');
|
||||
}
|
||||
m_defines.append(part->toolChainMacros);
|
||||
m_defines.append(part->projectMacros);
|
||||
if (!part->projectConfigFile.isEmpty())
|
||||
m_defines += ProjectExplorer::Macro::toMacros(ProjectPart::readProjectConfigFile(part));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -123,7 +123,7 @@ private:
|
||||
// The members below are (re)calculated from the project parts with finish()
|
||||
ProjectPartHeaderPaths m_headerPaths;
|
||||
QSet<QString> m_sourceFiles;
|
||||
QByteArray m_defines;
|
||||
ProjectExplorer::Macros m_defines;
|
||||
};
|
||||
|
||||
} // namespace CppTools
|
||||
|
@@ -25,6 +25,8 @@
|
||||
|
||||
#include "projectpart.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QTextStream>
|
||||
@@ -43,16 +45,9 @@ void ProjectPart::updateLanguageFeatures()
|
||||
if (!hasQt) {
|
||||
languageFeatures.qtKeywordsEnabled = false;
|
||||
} else {
|
||||
const QByteArray noKeywordsMacro = "#define QT_NO_KEYWORDS";
|
||||
const int noKeywordsIndex = projectDefines.indexOf(noKeywordsMacro);
|
||||
if (noKeywordsIndex == -1) {
|
||||
languageFeatures.qtKeywordsEnabled = true;
|
||||
} else {
|
||||
const char nextChar = projectDefines.at(noKeywordsIndex + noKeywordsMacro.length());
|
||||
// Detect "#define QT_NO_KEYWORDS" and "#define QT_NO_KEYWORDS 1", but exclude
|
||||
// "#define QT_NO_KEYWORDS_FOO"
|
||||
languageFeatures.qtKeywordsEnabled = nextChar != '\n' && nextChar != ' ';
|
||||
}
|
||||
languageFeatures.qtKeywordsEnabled = !Utils::contains(
|
||||
projectMacros,
|
||||
[] (const ProjectExplorer::Macro ¯o) { return macro.key == "QT_NO_KEYWORDS"; });
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include "projectpartheaderpath.h"
|
||||
|
||||
#include <projectexplorer/projectexplorer_global.h>
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
|
||||
#include <coreplugin/id.h>
|
||||
|
||||
@@ -118,7 +119,7 @@ public:
|
||||
QStringList precompiledHeaders;
|
||||
ProjectPartHeaderPaths headerPaths;
|
||||
|
||||
QByteArray projectDefines;
|
||||
ProjectExplorer::Macros projectMacros;
|
||||
|
||||
LanguageVersion languageVersion = LatestCxxVersion;
|
||||
LanguageExtensions languageExtensions = NoExtensions;
|
||||
@@ -130,7 +131,7 @@ public:
|
||||
|
||||
Core::Id toolchainType;
|
||||
bool isMsvc2015Toolchain = false;
|
||||
QByteArray toolchainDefines;
|
||||
ProjectExplorer::Macros toolChainMacros;
|
||||
ToolChainWordWidth toolChainWordWidth = WordWidth32Bit;
|
||||
QString toolChainTargetTriple;
|
||||
};
|
||||
|
@@ -82,9 +82,9 @@ ToolChain::PredefinedMacrosRunner NimToolChain::createPredefinedMacrosRunner() c
|
||||
return ToolChain::PredefinedMacrosRunner();
|
||||
}
|
||||
|
||||
QByteArray NimToolChain::predefinedMacros(const QStringList &) const
|
||||
Macros NimToolChain::predefinedMacros(const QStringList &) const
|
||||
{
|
||||
return QByteArray();
|
||||
return Macros();
|
||||
}
|
||||
|
||||
ToolChain::CompilerFlags NimToolChain::compilerFlags(const QStringList &) const
|
||||
|
@@ -41,7 +41,7 @@ public:
|
||||
bool isValid() const override;
|
||||
|
||||
PredefinedMacrosRunner createPredefinedMacrosRunner() const override;
|
||||
QByteArray predefinedMacros(const QStringList &flags) const final;
|
||||
ProjectExplorer::Macros predefinedMacros(const QStringList &flags) const final;
|
||||
CompilerFlags compilerFlags(const QStringList &flags) const final;
|
||||
ProjectExplorer::WarningFlags warningFlags(const QStringList &flags) const final;
|
||||
|
||||
|
@@ -118,7 +118,7 @@ ToolChain::PredefinedMacrosRunner AbstractMsvcToolChain::createPredefinedMacrosR
|
||||
};
|
||||
}
|
||||
|
||||
QByteArray AbstractMsvcToolChain::predefinedMacros(const QStringList &cxxflags) const
|
||||
ProjectExplorer::Macros AbstractMsvcToolChain::predefinedMacros(const QStringList &cxxflags) const
|
||||
{
|
||||
return createPredefinedMacrosRunner()(cxxflags);
|
||||
}
|
||||
@@ -277,13 +277,6 @@ bool AbstractMsvcToolChain::canClone() const
|
||||
return true;
|
||||
}
|
||||
|
||||
// Function must be thread-safe!
|
||||
QByteArray AbstractMsvcToolChain::msvcPredefinedMacros(const QStringList,
|
||||
const Utils::Environment&) const
|
||||
{
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
bool AbstractMsvcToolChain::generateEnvironmentSettings(const Utils::Environment &env,
|
||||
const QString &batchFile,
|
||||
const QString &batchArgs,
|
||||
|
@@ -53,7 +53,7 @@ public:
|
||||
QString originalTargetTriple() const override;
|
||||
|
||||
PredefinedMacrosRunner createPredefinedMacrosRunner() const override;
|
||||
QByteArray predefinedMacros(const QStringList &cxxflags) const override;
|
||||
Macros predefinedMacros(const QStringList &cxxflags) const override;
|
||||
CompilerFlags compilerFlags(const QStringList &cxxflags) const override;
|
||||
WarningFlags warningFlags(const QStringList &cflags) const override;
|
||||
SystemHeaderPathsRunner createSystemHeaderPathsRunner() const override;
|
||||
@@ -92,13 +92,14 @@ protected:
|
||||
|
||||
static void inferWarningsForLevel(int warningLevel, WarningFlags &flags);
|
||||
virtual Utils::Environment readEnvironmentSetting(const Utils::Environment& env) const = 0;
|
||||
virtual QByteArray msvcPredefinedMacros(const QStringList cxxflags,
|
||||
const Utils::Environment& env) const;
|
||||
// Function must be thread-safe!
|
||||
virtual Macros msvcPredefinedMacros(const QStringList cxxflags,
|
||||
const Utils::Environment& env) const = 0;
|
||||
|
||||
|
||||
Utils::FileName m_debuggerCommand;
|
||||
mutable QMutex *m_predefinedMacrosMutex = nullptr;
|
||||
mutable QByteArray m_predefinedMacros;
|
||||
mutable Macros m_predefinedMacros;
|
||||
mutable Utils::Environment m_lastEnvironment; // Last checked 'incoming' environment.
|
||||
mutable Utils::Environment m_resultEnvironment; // Resulting environment for VC
|
||||
mutable QMutex *m_headerPathsMutex = nullptr;
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include "customparser.h"
|
||||
#include "customparserconfigdialog.h"
|
||||
#include "projectexplorerconstants.h"
|
||||
#include "projectmacro.h"
|
||||
#include "toolchainmanager.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
@@ -118,39 +119,24 @@ bool CustomToolChain::isValid() const
|
||||
|
||||
ToolChain::PredefinedMacrosRunner CustomToolChain::createPredefinedMacrosRunner() const
|
||||
{
|
||||
const QStringList theMacros = m_predefinedMacros;
|
||||
const Macros theMacros = m_predefinedMacros;
|
||||
|
||||
// This runner must be thread-safe!
|
||||
return [theMacros](const QStringList &cxxflags){
|
||||
QByteArray result;
|
||||
QStringList macros = theMacros;
|
||||
Macros macros = theMacros;
|
||||
for (const QString &cxxFlag : cxxflags) {
|
||||
if (cxxFlag.startsWith(QLatin1String("-D"))) {
|
||||
macros << cxxFlag.mid(2).trimmed();
|
||||
} else if (cxxFlag.startsWith(QLatin1String("-U"))) {
|
||||
const QString &removedName = cxxFlag.mid(2).trimmed();
|
||||
for (int i = macros.size() - 1; i >= 0; --i) {
|
||||
const QString &m = macros.at(i);
|
||||
if (m.left(m.indexOf(QLatin1Char('='))) == removedName)
|
||||
macros.removeAt(i);
|
||||
}
|
||||
}
|
||||
if (cxxFlag.startsWith(QLatin1String("-D")))
|
||||
macros.append(Macro::fromKeyValue(cxxFlag.mid(2).trimmed()));
|
||||
else if (cxxFlag.startsWith(QLatin1String("-U")) && !cxxFlag.contains('='))
|
||||
macros.append({cxxFlag.mid(2).trimmed().toUtf8(), MacroType::Undefine});
|
||||
|
||||
}
|
||||
for (const QString &str : Utils::asConst(macros)) {
|
||||
QByteArray ba = str.toUtf8();
|
||||
int equals = ba.indexOf('=');
|
||||
if (equals == -1) {
|
||||
result += "#define " + ba.trimmed() + '\n';
|
||||
} else {
|
||||
result += "#define " + ba.left(equals).trimmed() + ' '
|
||||
+ ba.mid(equals + 1).trimmed() + '\n';
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return macros;
|
||||
};
|
||||
}
|
||||
|
||||
QByteArray CustomToolChain::predefinedMacros(const QStringList &cxxflags) const
|
||||
Macros CustomToolChain::predefinedMacros(const QStringList &cxxflags) const
|
||||
{
|
||||
return createPredefinedMacrosRunner()(cxxflags);
|
||||
}
|
||||
@@ -169,16 +155,16 @@ WarningFlags CustomToolChain::warningFlags(const QStringList &cxxflags) const
|
||||
return WarningFlags::Default;
|
||||
}
|
||||
|
||||
const QStringList &CustomToolChain::rawPredefinedMacros() const
|
||||
const Macros &CustomToolChain::rawPredefinedMacros() const
|
||||
{
|
||||
return m_predefinedMacros;
|
||||
}
|
||||
|
||||
void CustomToolChain::setPredefinedMacros(const QStringList &list)
|
||||
void CustomToolChain::setPredefinedMacros(const Macros ¯os)
|
||||
{
|
||||
if (m_predefinedMacros == list)
|
||||
if (m_predefinedMacros == macros)
|
||||
return;
|
||||
m_predefinedMacros = list;
|
||||
m_predefinedMacros = macros;
|
||||
toolChainUpdated();
|
||||
}
|
||||
|
||||
@@ -323,7 +309,8 @@ QVariantMap CustomToolChain::toMap() const
|
||||
data.insert(QLatin1String(compilerCommandKeyC), m_compilerCommand.toString());
|
||||
data.insert(QLatin1String(makeCommandKeyC), m_makeCommand.toString());
|
||||
data.insert(QLatin1String(targetAbiKeyC), m_targetAbi.toString());
|
||||
data.insert(QLatin1String(predefinedMacrosKeyC), m_predefinedMacros);
|
||||
QStringList macros = Utils::transform<QList>(m_predefinedMacros, [](const Macro &m) { return QString::fromUtf8(m.toByteArray()); });
|
||||
data.insert(QLatin1String(predefinedMacrosKeyC), macros);
|
||||
data.insert(QLatin1String(headerPathsKeyC), headerPathsList());
|
||||
data.insert(QLatin1String(cxx11FlagsKeyC), m_cxx11Flags);
|
||||
data.insert(QLatin1String(mkspecsKeyC), mkspecs());
|
||||
@@ -352,7 +339,8 @@ bool CustomToolChain::fromMap(const QVariantMap &data)
|
||||
m_compilerCommand = FileName::fromString(data.value(QLatin1String(compilerCommandKeyC)).toString());
|
||||
m_makeCommand = FileName::fromString(data.value(QLatin1String(makeCommandKeyC)).toString());
|
||||
m_targetAbi = Abi(data.value(QLatin1String(targetAbiKeyC)).toString());
|
||||
m_predefinedMacros = data.value(QLatin1String(predefinedMacrosKeyC)).toStringList();
|
||||
const QStringList macros = data.value(QLatin1String(predefinedMacrosKeyC)).toStringList();
|
||||
m_predefinedMacros = Macro::toMacros(macros.join('\n').toUtf8());
|
||||
setHeaderPaths(data.value(QLatin1String(headerPathsKeyC)).toStringList());
|
||||
m_cxx11Flags = data.value(QLatin1String(cxx11FlagsKeyC)).toStringList();
|
||||
setMkspecs(data.value(QLatin1String(mkspecsKeyC)).toString());
|
||||
@@ -526,11 +514,16 @@ public:
|
||||
return static_cast<QPlainTextEdit *>(widget());
|
||||
}
|
||||
|
||||
inline QStringList entries() const
|
||||
QStringList entries() const
|
||||
{
|
||||
return textEditWidget()->toPlainText().split(QLatin1Char('\n'), QString::SkipEmptyParts);
|
||||
}
|
||||
|
||||
QString text() const
|
||||
{
|
||||
return textEditWidget()->toPlainText();
|
||||
}
|
||||
|
||||
// not accurate, counts empty lines (except last)
|
||||
int entryCount() const
|
||||
{
|
||||
@@ -656,7 +649,7 @@ void CustomToolChainConfigWidget::applyImpl()
|
||||
tc->setCompilerCommand(m_compilerCommand->fileName());
|
||||
tc->setMakeCommand(m_makeCommand->fileName());
|
||||
tc->setTargetAbi(m_abiWidget->currentAbi());
|
||||
tc->setPredefinedMacros(m_predefinedDetails->entries());
|
||||
tc->setPredefinedMacros(Macro::toMacros(m_predefinedDetails->text().toUtf8()));
|
||||
tc->setHeaderPaths(m_headerDetails->entries());
|
||||
tc->setCxx11Flags(m_cxx11Flags->text().split(QLatin1Char(',')));
|
||||
tc->setMkspecs(m_mkspecs->text());
|
||||
@@ -673,8 +666,8 @@ void CustomToolChainConfigWidget::setFromToolchain()
|
||||
m_compilerCommand->setFileName(tc->compilerCommand());
|
||||
m_makeCommand->setFileName(FileName::fromString(tc->makeCommand(Environment())));
|
||||
m_abiWidget->setAbis(QList<Abi>(), tc->targetAbi());
|
||||
m_predefinedMacros->setPlainText(tc->rawPredefinedMacros().join(QLatin1Char('\n')));
|
||||
m_headerPaths->setPlainText(tc->headerPathsList().join(QLatin1Char('\n')));
|
||||
m_predefinedMacros->setPlainText(QString::fromUtf8(Macro::toByteArray(tc->rawPredefinedMacros())));
|
||||
m_headerPaths->setPlainText(tc->headerPathsList().join('\n'));
|
||||
m_cxx11Flags->setText(tc->cxx11Flags().join(QLatin1Char(',')));
|
||||
m_mkspecs->setText(tc->mkspecs());
|
||||
int index = m_errorParserComboBox->findData(tc->outputParserId().toSetting());
|
||||
@@ -690,7 +683,7 @@ bool CustomToolChainConfigWidget::isDirtyImpl() const
|
||||
return m_compilerCommand->fileName() != tc->compilerCommand()
|
||||
|| m_makeCommand->path() != tc->makeCommand(Environment())
|
||||
|| m_abiWidget->currentAbi() != tc->targetAbi()
|
||||
|| m_predefinedDetails->entries() != tc->rawPredefinedMacros()
|
||||
|| Macro::toMacros(m_predefinedDetails->text().toUtf8()) != tc->rawPredefinedMacros()
|
||||
|| m_headerDetails->entries() != tc->headerPathsList()
|
||||
|| m_cxx11Flags->text().split(QLatin1Char(',')) != tc->cxx11Flags()
|
||||
|| m_mkspecs->text() != tc->mkspecs()
|
||||
|
@@ -72,11 +72,11 @@ public:
|
||||
bool isValid() const override;
|
||||
|
||||
PredefinedMacrosRunner createPredefinedMacrosRunner() const override;
|
||||
QByteArray predefinedMacros(const QStringList &cxxflags) const override;
|
||||
Macros predefinedMacros(const QStringList &cxxflags) const override;
|
||||
CompilerFlags compilerFlags(const QStringList &cxxflags) const override;
|
||||
WarningFlags warningFlags(const QStringList &cxxflags) const override;
|
||||
const QStringList &rawPredefinedMacros() const;
|
||||
void setPredefinedMacros(const QStringList &list);
|
||||
const Macros &rawPredefinedMacros() const;
|
||||
void setPredefinedMacros(const Macros ¯os);
|
||||
|
||||
SystemHeaderPathsRunner createSystemHeaderPathsRunner() const override;
|
||||
QList<HeaderPath> systemHeaderPaths(const QStringList &cxxFlags,
|
||||
@@ -124,7 +124,7 @@ private:
|
||||
Utils::FileName m_makeCommand;
|
||||
|
||||
Abi m_targetAbi;
|
||||
QStringList m_predefinedMacros;
|
||||
Macros m_predefinedMacros;
|
||||
QList<HeaderPath> m_systemHeaderPaths;
|
||||
QStringList m_cxx11Flags;
|
||||
Utils::FileNameList m_mkspecs;
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include "gcctoolchainfactories.h"
|
||||
#include "gccparser.h"
|
||||
#include "linuxiccparser.h"
|
||||
#include "projectmacro.h"
|
||||
#include "projectexplorerconstants.h"
|
||||
#include "toolchainmanager.h"
|
||||
|
||||
@@ -48,6 +49,7 @@
|
||||
#include <QLineEdit>
|
||||
#include <QRegularExpression>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
using namespace Utils;
|
||||
@@ -119,6 +121,11 @@ HeaderPathsCache::Cache HeaderPathsCache::cache() const
|
||||
return m_cache;
|
||||
}
|
||||
|
||||
MacroCache::MacroCache() : m_mutex(QMutex::Recursive)
|
||||
{
|
||||
m_cache.reserve(CACHE_SIZE + 1);
|
||||
}
|
||||
|
||||
MacroCache::MacroCache(const MacroCache &other)
|
||||
: MacroCache()
|
||||
{
|
||||
@@ -126,40 +133,21 @@ MacroCache::MacroCache(const MacroCache &other)
|
||||
m_cache = other.cache();
|
||||
}
|
||||
|
||||
void MacroCache::insert(const QStringList &compilerCommand, const QByteArray ¯os)
|
||||
void MacroCache::insert(const QStringList &compilerCommand, const Macros ¯os)
|
||||
{
|
||||
if (macros.isNull())
|
||||
QMutexLocker locker(&m_mutex);
|
||||
if (macros.isEmpty() || unlockedCheck(compilerCommand).isEmpty())
|
||||
return;
|
||||
|
||||
CacheItem runResults;
|
||||
QByteArray data = macros;
|
||||
runResults.first = compilerCommand;
|
||||
if (macros.isNull())
|
||||
data = QByteArray("");
|
||||
runResults.second = data;
|
||||
|
||||
QMutexLocker locker(&m_mutex);
|
||||
if (check(compilerCommand).isNull()) {
|
||||
m_cache.push_back(runResults);
|
||||
if (m_cache.size() > CACHE_SIZE)
|
||||
m_cache.pop_front();
|
||||
}
|
||||
m_cache.push_back(qMakePair(compilerCommand, macros));
|
||||
if (m_cache.size() > CACHE_SIZE)
|
||||
m_cache.pop_front();
|
||||
}
|
||||
|
||||
QByteArray MacroCache::check(const QStringList &compilerCommand) const
|
||||
Macros MacroCache::check(const QStringList &compilerCommand) const
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
for (Cache::iterator it = m_cache.begin(); it != m_cache.end(); ++it) {
|
||||
if (it->first == compilerCommand) {
|
||||
// Increase cached item priority
|
||||
CacheItem pair = *it;
|
||||
m_cache.erase(it);
|
||||
m_cache.push_back(pair);
|
||||
|
||||
return pair.second;
|
||||
}
|
||||
}
|
||||
return QByteArray();
|
||||
return unlockedCheck(compilerCommand);
|
||||
}
|
||||
|
||||
MacroCache::Cache MacroCache::cache() const
|
||||
@@ -168,6 +156,16 @@ MacroCache::Cache MacroCache::cache() const
|
||||
return m_cache;
|
||||
}
|
||||
|
||||
Macros MacroCache::unlockedCheck(const QStringList &compilerCommand) const
|
||||
{
|
||||
auto it = std::stable_partition(m_cache.begin(), m_cache.end(), [&](const CacheItem &ci) {
|
||||
return ci.first == compilerCommand;
|
||||
});
|
||||
if (it != m_cache.end())
|
||||
return it->second;
|
||||
return {};
|
||||
}
|
||||
|
||||
static QByteArray runGcc(const FileName &gcc, const QStringList &arguments, const QStringList &env)
|
||||
{
|
||||
if (gcc.isEmpty() || !gcc.toFileInfo().isExecutable())
|
||||
@@ -196,25 +194,28 @@ static const QStringList gccPredefinedMacrosOptions(Core::Id languageId)
|
||||
return QStringList({langOption, "-E", "-dM"});
|
||||
}
|
||||
|
||||
static QByteArray gccPredefinedMacros(const FileName &gcc, const QStringList &args, const QStringList &env)
|
||||
static ProjectExplorer::Macros gccPredefinedMacros(const FileName &gcc,
|
||||
const QStringList &args,
|
||||
const QStringList &env)
|
||||
{
|
||||
QStringList arguments = args;
|
||||
arguments << "-";
|
||||
|
||||
QByteArray predefinedMacros = runGcc(gcc, arguments, env);
|
||||
ProjectExplorer::Macros predefinedMacros = Macro::toMacros(runGcc(gcc, arguments, env));
|
||||
// Sanity check in case we get an error message instead of real output:
|
||||
QTC_CHECK(predefinedMacros.isNull() || predefinedMacros.startsWith("#define "));
|
||||
QTC_CHECK(predefinedMacros.isEmpty()
|
||||
|| predefinedMacros.front().type == ProjectExplorer::MacroType::Define);
|
||||
if (HostOsInfo::isMacHost()) {
|
||||
// Turn off flag indicating Apple's blocks support
|
||||
const QByteArray blocksDefine("#define __BLOCKS__ 1");
|
||||
const QByteArray blocksUndefine("#undef __BLOCKS__");
|
||||
const ProjectExplorer::Macro blocksDefine("__BLOCKS__", "1");
|
||||
const ProjectExplorer::Macro blocksUndefine("__BLOCKS__", ProjectExplorer::MacroType::Undefine);
|
||||
const int idx = predefinedMacros.indexOf(blocksDefine);
|
||||
if (idx != -1)
|
||||
predefinedMacros.replace(idx, blocksDefine.length(), blocksUndefine);
|
||||
predefinedMacros[idx] = blocksUndefine;
|
||||
|
||||
// Define __strong and __weak (used for Apple's GC extension of C) to be empty
|
||||
predefinedMacros.append("#define __strong\n");
|
||||
predefinedMacros.append("#define __weak\n");
|
||||
predefinedMacros.append({"__strong"});
|
||||
predefinedMacros.append({"__weak"});
|
||||
}
|
||||
return predefinedMacros;
|
||||
}
|
||||
@@ -261,7 +262,7 @@ QList<HeaderPath> GccToolChain::gccHeaderPaths(const FileName &gcc, const QStrin
|
||||
return systemHeaderPaths;
|
||||
}
|
||||
|
||||
static QList<Abi> guessGccAbi(const QString &m, const QByteArray ¯os)
|
||||
static QList<Abi> guessGccAbi(const QString &m, const ProjectExplorer::Macros ¯os)
|
||||
{
|
||||
QList<Abi> abiList;
|
||||
|
||||
@@ -274,19 +275,13 @@ static QList<Abi> guessGccAbi(const QString &m, const QByteArray ¯os)
|
||||
Abi::OSFlavor flavor = guessed.osFlavor();
|
||||
Abi::BinaryFormat format = guessed.binaryFormat();
|
||||
int width = guessed.wordWidth();
|
||||
const QByteArray mscVer = "#define _MSC_VER ";
|
||||
|
||||
if (macros.contains("#define __SIZEOF_SIZE_T__ 8"))
|
||||
width = 64;
|
||||
else if (macros.contains("#define __SIZEOF_SIZE_T__ 4"))
|
||||
width = 32;
|
||||
else if (macros.contains("#define __SIZEOF_SIZE_T__ 2"))
|
||||
width = 16;
|
||||
int mscVerIndex = macros.indexOf(mscVer);
|
||||
if (mscVerIndex != -1) {
|
||||
mscVerIndex += mscVer.length();
|
||||
const int eol = macros.indexOf('\n', mscVerIndex);
|
||||
const int msvcVersion = macros.mid(mscVerIndex, eol - mscVerIndex).toInt();
|
||||
const Macro sizeOfMacro = Utils::findOrDefault(macros, [](const Macro &m) { return m.key == "__SIZEOF_SIZE_T__"; });
|
||||
if (sizeOfMacro.isValid() && sizeOfMacro.type == MacroType::Define)
|
||||
width = sizeOfMacro.value.toInt() * 8;
|
||||
const Macro &mscVerMacro = Utils::findOrDefault(macros, [](const Macro &m) { return m.key == "_MSC_VER"; });
|
||||
if (mscVerMacro.type == MacroType::Define) {
|
||||
const int msvcVersion = mscVerMacro.value.toInt();
|
||||
flavor = Abi::flavorForMsvcVersion(msvcVersion);
|
||||
}
|
||||
|
||||
@@ -305,7 +300,7 @@ static QList<Abi> guessGccAbi(const QString &m, const QByteArray ¯os)
|
||||
|
||||
|
||||
static GccToolChain::DetectedAbisResult guessGccAbi(const FileName &path, const QStringList &env,
|
||||
const QByteArray ¯os,
|
||||
const ProjectExplorer::Macros ¯os,
|
||||
const QStringList &extraArgs = QStringList())
|
||||
{
|
||||
if (path.isEmpty())
|
||||
@@ -495,8 +490,8 @@ ToolChain::PredefinedMacrosRunner GccToolChain::createPredefinedMacrosRunner() c
|
||||
}
|
||||
|
||||
arguments = reinterpretOptions(arguments);
|
||||
QByteArray macros = macroCache->check(arguments);
|
||||
if (!macros.isNull())
|
||||
Macros macros = macroCache->check(arguments);
|
||||
if (!macros.isEmpty())
|
||||
return macros;
|
||||
|
||||
macros = gccPredefinedMacros(findLocalCompiler(compilerCommand, env),
|
||||
@@ -517,7 +512,7 @@ ToolChain::PredefinedMacrosRunner GccToolChain::createPredefinedMacrosRunner() c
|
||||
* adds _OPENMP macro, for full list of macro search by word "when" on this page:
|
||||
* http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
|
||||
*/
|
||||
QByteArray GccToolChain::predefinedMacros(const QStringList &cxxflags) const
|
||||
ProjectExplorer::Macros GccToolChain::predefinedMacros(const QStringList &cxxflags) const
|
||||
{
|
||||
return createPredefinedMacrosRunner()(cxxflags);
|
||||
}
|
||||
@@ -701,6 +696,8 @@ void GccToolChain::addCommandPathToEnvironment(const FileName &command, Environm
|
||||
env.prependOrSetPath(command.parentDir().toString());
|
||||
}
|
||||
|
||||
GccToolChain::GccToolChain(const GccToolChain &) = default;
|
||||
|
||||
void GccToolChain::addToEnvironment(Environment &env) const
|
||||
{
|
||||
addCommandPathToEnvironment(m_compilerCommand, env);
|
||||
@@ -898,7 +895,7 @@ GccToolChain::DetectedAbisResult GccToolChain::detectSupportedAbis() const
|
||||
{
|
||||
Environment env = Environment::systemEnvironment();
|
||||
addToEnvironment(env);
|
||||
QByteArray macros = predefinedMacros(QStringList());
|
||||
ProjectExplorer::Macros macros = predefinedMacros(QStringList());
|
||||
return guessGccAbi(findLocalCompiler(m_compilerCommand, env),
|
||||
env.toStringList(),
|
||||
macros,
|
||||
@@ -1060,7 +1057,7 @@ QList<ToolChain *> GccToolChainFactory::autoDetectToolChain(const FileName &comp
|
||||
Environment systemEnvironment = Environment::systemEnvironment();
|
||||
GccToolChain::addCommandPathToEnvironment(compilerPath, systemEnvironment);
|
||||
const FileName localCompilerPath = findLocalCompiler(compilerPath, systemEnvironment);
|
||||
QByteArray macros
|
||||
Macros macros
|
||||
= gccPredefinedMacros(localCompilerPath, gccPredefinedMacrosOptions(language),
|
||||
systemEnvironment.toStringList());
|
||||
const GccToolChain::DetectedAbisResult detectedAbis = guessGccAbi(localCompilerPath,
|
||||
@@ -1765,7 +1762,7 @@ void ProjectExplorerPlugin::testGccAbiGuessing()
|
||||
QFETCH(QByteArray, macros);
|
||||
QFETCH(QStringList, abiList);
|
||||
|
||||
QList<Abi> al = guessGccAbi(input, macros);
|
||||
QList<Abi> al = guessGccAbi(input, ProjectExplorer::Macro::toMacros(macros));
|
||||
QCOMPARE(al.count(), abiList.count());
|
||||
for (int i = 0; i < al.count(); ++i)
|
||||
QCOMPARE(al.at(i).toString(), abiList.at(i));
|
||||
|
@@ -51,7 +51,7 @@ class LinuxIccToolChainFactory;
|
||||
// GccToolChain
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
class PROJECTEXPLORER_EXPORT HeaderPathsCache
|
||||
class HeaderPathsCache
|
||||
{
|
||||
public:
|
||||
HeaderPathsCache() : m_mutex(QMutex::Recursive) {}
|
||||
@@ -69,20 +69,22 @@ private:
|
||||
mutable Cache m_cache;
|
||||
};
|
||||
|
||||
class PROJECTEXPLORER_EXPORT MacroCache
|
||||
class MacroCache
|
||||
{
|
||||
public:
|
||||
MacroCache() : m_mutex(QMutex::Recursive) {}
|
||||
MacroCache();
|
||||
MacroCache(const MacroCache &other);
|
||||
void insert(const QStringList &compilerCommand, const QByteArray ¯os);
|
||||
QByteArray check(const QStringList &compilerCommand) const;
|
||||
void insert(const QStringList &compilerCommand, const Macros ¯os);
|
||||
Macros check(const QStringList &compilerCommand) const;
|
||||
|
||||
protected:
|
||||
using CacheItem = QPair<QStringList, QByteArray>;
|
||||
using Cache = QList<CacheItem>;
|
||||
using CacheItem = QPair<QStringList, Macros>;
|
||||
using Cache = QVector<CacheItem>;
|
||||
Cache cache() const;
|
||||
|
||||
private:
|
||||
// Does not lock!
|
||||
Macros unlockedCheck(const QStringList &compilerCommand) const;
|
||||
mutable QMutex m_mutex;
|
||||
mutable Cache m_cache;
|
||||
};
|
||||
@@ -104,7 +106,7 @@ public:
|
||||
WarningFlags warningFlags(const QStringList &cflags) const override;
|
||||
|
||||
PredefinedMacrosRunner createPredefinedMacrosRunner() const override;
|
||||
QByteArray predefinedMacros(const QStringList &cxxflags) const override;
|
||||
Macros predefinedMacros(const QStringList &cxxflags) const override;
|
||||
|
||||
SystemHeaderPathsRunner createSystemHeaderPathsRunner() const override;
|
||||
QList<HeaderPath> systemHeaderPaths(const QStringList &cxxflags,
|
||||
@@ -147,14 +149,16 @@ public:
|
||||
};
|
||||
|
||||
protected:
|
||||
GccToolChain(const GccToolChain &) = default;
|
||||
using CacheItem = QPair<QStringList, Macros>;
|
||||
using GccCache = QVector<CacheItem>;
|
||||
|
||||
GccToolChain(const GccToolChain &);
|
||||
|
||||
void setCompilerCommand(const Utils::FileName &path);
|
||||
void setSupportedAbis(const QList<Abi> &m_abis);
|
||||
void setOriginalTargetTriple(const QString &targetTriple);
|
||||
|
||||
void setMacroCache(const QStringList &allCxxflags, const QByteArray ¯os) const;
|
||||
QByteArray macroCache(const QStringList &allCxxflags) const;
|
||||
void setMacroCache(const QStringList &allCxxflags, const Macros ¯oCache) const;
|
||||
Macros macroCache(const QStringList &allCxxflags) const;
|
||||
|
||||
virtual QString defaultDisplayName() const;
|
||||
virtual CompilerFlags defaultCompilerFlags() const;
|
||||
|
@@ -99,7 +99,7 @@ private:
|
||||
AbiWidget *m_abiWidget;
|
||||
|
||||
bool m_isReadOnly = false;
|
||||
QByteArray m_macros;
|
||||
ProjectExplorer::Macros m_macros;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
|
@@ -410,31 +410,18 @@ static QByteArray msvcCompilationFile()
|
||||
//
|
||||
// [1] https://msdn.microsoft.com/en-us/library/b0084kay.aspx
|
||||
// [2] http://stackoverflow.com/questions/3665537/how-to-find-out-cl-exes-built-in-macros
|
||||
QByteArray MsvcToolChain::msvcPredefinedMacros(const QStringList cxxflags,
|
||||
const Utils::Environment &env) const
|
||||
Macros MsvcToolChain::msvcPredefinedMacros(const QStringList cxxflags,
|
||||
const Utils::Environment &env) const
|
||||
{
|
||||
QByteArray predefinedMacros;
|
||||
Macros predefinedMacros;
|
||||
|
||||
QStringList toProcess;
|
||||
foreach (const QString &arg, cxxflags) {
|
||||
for (const QString &arg : cxxflags) {
|
||||
if (arg.startsWith(QLatin1String("/D"))) {
|
||||
QString define = arg.mid(2);
|
||||
int pos = define.indexOf(QLatin1Char('='));
|
||||
if (pos < 0) {
|
||||
predefinedMacros += "#define ";
|
||||
predefinedMacros += define.toLocal8Bit();
|
||||
predefinedMacros += '\n';
|
||||
} else {
|
||||
predefinedMacros += "#define ";
|
||||
predefinedMacros += define.left(pos).toLocal8Bit();
|
||||
predefinedMacros += ' ';
|
||||
predefinedMacros += define.mid(pos + 1).toLocal8Bit();
|
||||
predefinedMacros += '\n';
|
||||
}
|
||||
const QString define = arg.mid(2);
|
||||
predefinedMacros.append(Macro::fromKeyValue(define));
|
||||
} else if (arg.startsWith(QLatin1String("/U"))) {
|
||||
predefinedMacros += "#undef ";
|
||||
predefinedMacros += arg.mid(2).toLocal8Bit();
|
||||
predefinedMacros += '\n';
|
||||
predefinedMacros.append({arg.mid(2).toLocal8Bit(), ProjectExplorer::MacroType::Undefine});
|
||||
} else if (arg.startsWith(QLatin1String("-I"))) {
|
||||
// Include paths should not have any effect on defines
|
||||
} else {
|
||||
@@ -468,18 +455,8 @@ QByteArray MsvcToolChain::msvcPredefinedMacros(const QStringList cxxflags,
|
||||
|
||||
const QStringList output = Utils::filtered(response.stdOut().split('\n'),
|
||||
[](const QString &s) { return s.startsWith('V'); });
|
||||
foreach (const QString& line, output) {
|
||||
QStringList split = line.split('=');
|
||||
const QString key = split.at(0).mid(1);
|
||||
QString value = split.at(1);
|
||||
predefinedMacros += "#define ";
|
||||
predefinedMacros += key.toUtf8();
|
||||
predefinedMacros += ' ';
|
||||
predefinedMacros += value.toUtf8();
|
||||
predefinedMacros += '\n';
|
||||
}
|
||||
if (debug)
|
||||
qDebug() << "msvcPredefinedMacros" << predefinedMacros;
|
||||
for (const QString &line : output)
|
||||
predefinedMacros.append(Macro::fromKeyValue(line.mid(1)));
|
||||
return predefinedMacros;
|
||||
}
|
||||
|
||||
|
@@ -82,8 +82,8 @@ protected:
|
||||
|
||||
Utils::Environment readEnvironmentSetting(const Utils::Environment& env) const final;
|
||||
// Function must be thread-safe!
|
||||
QByteArray msvcPredefinedMacros(const QStringList cxxflags,
|
||||
const Utils::Environment &env) const override;
|
||||
Macros msvcPredefinedMacros(const QStringList cxxflags,
|
||||
const Utils::Environment &env) const override;
|
||||
|
||||
private:
|
||||
QList<Utils::EnvironmentItem> environmentModifications() const;
|
||||
|
@@ -149,7 +149,8 @@ HEADERS += projectexplorer.h \
|
||||
projectexplorer_global.h \
|
||||
extracompiler.h \
|
||||
customexecutableconfigurationwidget.h \
|
||||
customexecutablerunconfiguration.h
|
||||
customexecutablerunconfiguration.h \
|
||||
projectmacro.h
|
||||
|
||||
SOURCES += projectexplorer.cpp \
|
||||
abi.cpp \
|
||||
@@ -284,7 +285,8 @@ SOURCES += projectexplorer.cpp \
|
||||
projectexplorericons.cpp \
|
||||
extracompiler.cpp \
|
||||
customexecutableconfigurationwidget.cpp \
|
||||
customexecutablerunconfiguration.cpp
|
||||
customexecutablerunconfiguration.cpp \
|
||||
projectmacro.cpp
|
||||
|
||||
FORMS += processstep.ui \
|
||||
editorsettingspropertiespage.ui \
|
||||
|
12
src/plugins/projectexplorer/projectexplorerunittestfiles.pri
Normal file
12
src/plugins/projectexplorer/projectexplorerunittestfiles.pri
Normal file
@@ -0,0 +1,12 @@
|
||||
shared {
|
||||
DEFINES += PROJECTEXPLORER_LIBRARY
|
||||
} else {
|
||||
DEFINES += PROJECTEXPLORER_STATIC_LIBRARY
|
||||
}
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/projectmacro.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/projectmacro.cpp
|
||||
|
219
src/plugins/projectexplorer/projectmacro.cpp
Normal file
219
src/plugins/projectexplorer/projectmacro.cpp
Normal file
@@ -0,0 +1,219 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 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 "projectmacro.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
bool Macro::isValid() const
|
||||
{
|
||||
return !key.isEmpty() && type != MacroType::Invalid;
|
||||
}
|
||||
|
||||
QByteArray Macro::toByteArray() const
|
||||
{
|
||||
switch (type) {
|
||||
case MacroType::Define: return QByteArray("#define ") + key + ' ' + value;
|
||||
case MacroType::Undefine: return QByteArray("#undef ") + key;
|
||||
case MacroType::Invalid: break;
|
||||
}
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray Macro::toByteArray(const Macros ¯os)
|
||||
{
|
||||
QByteArray text;
|
||||
|
||||
for (const Macro ¯o : macros) {
|
||||
const QByteArray macroText = macro.toByteArray();
|
||||
if (!macroText.isEmpty())
|
||||
text += macroText + '\n';
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
QByteArray Macro::toByteArray(const QVector<Macros> ¯osVector)
|
||||
{
|
||||
QByteArray text;
|
||||
|
||||
for (const Macros ¯os : macrosVector)
|
||||
text += toByteArray(macros);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
Macros Macro::toMacros(const QByteArray &text)
|
||||
{
|
||||
return tokensLinesToMacros(tokenizeLines(splitLines(text)));
|
||||
}
|
||||
|
||||
Macro Macro::fromKeyValue(const QString &utf16text)
|
||||
{
|
||||
return fromKeyValue(utf16text.toUtf8());
|
||||
}
|
||||
|
||||
Macro Macro::fromKeyValue(const QByteArray &text)
|
||||
{
|
||||
QByteArray key;
|
||||
QByteArray value;
|
||||
MacroType type = MacroType::Invalid;
|
||||
|
||||
if (!text.isEmpty()) {
|
||||
type = MacroType::Define;
|
||||
|
||||
int index = text.indexOf('=');
|
||||
|
||||
if (index != -1) {
|
||||
key = text.left(index).trimmed();
|
||||
value = text.mid(index + 1).trimmed();
|
||||
} else {
|
||||
key = text.trimmed();
|
||||
value = "1";
|
||||
}
|
||||
}
|
||||
|
||||
return Macro(key, value, type);
|
||||
}
|
||||
|
||||
QByteArray Macro::toKeyValue(const QByteArray &prefix) const
|
||||
{
|
||||
QByteArray keyValue;
|
||||
if (type != MacroType::Invalid)
|
||||
keyValue = prefix;
|
||||
|
||||
if (value.isEmpty())
|
||||
keyValue += key;
|
||||
else
|
||||
keyValue += key + '=' + value;
|
||||
|
||||
return keyValue;
|
||||
}
|
||||
|
||||
static void removeCarriageReturn(QByteArray &line)
|
||||
{
|
||||
if (line.endsWith('\r'))
|
||||
line.truncate(line.size() - 1);
|
||||
}
|
||||
|
||||
static void removeCarriageReturns(QList<QByteArray> &lines)
|
||||
{
|
||||
for (QByteArray &line : lines)
|
||||
removeCarriageReturn(line);
|
||||
}
|
||||
|
||||
QList<QByteArray> Macro::splitLines(const QByteArray &text)
|
||||
{
|
||||
QList<QByteArray> splitLines = text.split('\n');
|
||||
|
||||
splitLines.removeAll("");
|
||||
removeCarriageReturns(splitLines);
|
||||
|
||||
return splitLines;
|
||||
}
|
||||
|
||||
QByteArray Macro::removeNonsemanticSpaces(QByteArray line)
|
||||
{
|
||||
auto begin = line.begin();
|
||||
auto end = line.end();
|
||||
bool notInString = true;
|
||||
|
||||
auto newEnd = std::unique(begin, end, [&] (char first, char second) {
|
||||
notInString = notInString && first != '\"';
|
||||
return notInString && (first == '#' || std::isspace(first)) && std::isspace(second);
|
||||
});
|
||||
|
||||
line.truncate(line.size() - int(std::distance(newEnd, end)));
|
||||
|
||||
return line.trimmed();
|
||||
}
|
||||
|
||||
QList<QByteArray> Macro::tokenizeLine(const QByteArray &line)
|
||||
{
|
||||
const QByteArray normalizedLine = removeNonsemanticSpaces(line);
|
||||
|
||||
const auto begin = normalizedLine.begin();
|
||||
auto first = std::find(normalizedLine.begin(), normalizedLine.end(), ' ');
|
||||
auto second = std::find(std::next(first), normalizedLine.end(), ' ');
|
||||
const auto end = normalizedLine.end();
|
||||
|
||||
QList<QByteArray> tokens;
|
||||
|
||||
if (first != end) {
|
||||
tokens.append(QByteArray(begin, int(std::distance(begin, first))));
|
||||
|
||||
std::advance(first, 1);
|
||||
tokens.append(QByteArray(first, int(std::distance(first, second))));
|
||||
|
||||
if (second != end) {
|
||||
std::advance(second, 1);
|
||||
tokens.append(QByteArray(second, int(std::distance(second, end))));
|
||||
}
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
QList<QList<QByteArray>> Macro::tokenizeLines(const QList<QByteArray> &lines)
|
||||
{
|
||||
QList<QList<QByteArray>> tokensLines = Utils::transform(lines, &Macro::tokenizeLine);
|
||||
|
||||
return tokensLines;
|
||||
}
|
||||
|
||||
Macro Macro::tokensToMacro(const QList<QByteArray> &tokens)
|
||||
{
|
||||
Macro macro;
|
||||
|
||||
if (tokens.size() >= 2 && tokens[0] == "#define") {
|
||||
macro.type = MacroType::Define;
|
||||
macro.key = tokens[1];
|
||||
|
||||
if (tokens.size() >= 3)
|
||||
macro.value = tokens[2];
|
||||
}
|
||||
|
||||
return macro;
|
||||
}
|
||||
|
||||
Macros Macro::tokensLinesToMacros(const QList<QList<QByteArray>> &tokensLines)
|
||||
{
|
||||
Macros macros;
|
||||
macros.reserve(tokensLines.size());
|
||||
|
||||
for (const QList<QByteArray> &tokens : tokensLines) {
|
||||
Macro macro = tokensToMacro(tokens);
|
||||
|
||||
if (macro.type != MacroType::Invalid)
|
||||
macros.push_back(std::move(macro));
|
||||
}
|
||||
|
||||
return macros;
|
||||
}
|
||||
|
||||
} // namespace ProjectExplorer
|
102
src/plugins/projectexplorer/projectmacro.h
Normal file
102
src/plugins/projectexplorer/projectmacro.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 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 "projectexplorer_export.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QHash>
|
||||
#include <QVector>
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
enum class MacroType
|
||||
{
|
||||
Invalid,
|
||||
Define,
|
||||
Undefine
|
||||
};
|
||||
|
||||
class Macro;
|
||||
|
||||
using Macros = QVector<Macro>;
|
||||
|
||||
class PROJECTEXPLORER_EXPORT Macro
|
||||
{
|
||||
public:
|
||||
Macro() = default;
|
||||
|
||||
Macro(QByteArray key, QByteArray value, MacroType type = MacroType::Define)
|
||||
: key(key), value(value), type(type)
|
||||
{}
|
||||
|
||||
Macro(QByteArray key, MacroType type = MacroType::Define)
|
||||
: key(key), type(type)
|
||||
{}
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
QByteArray toByteArray() const;
|
||||
static QByteArray toByteArray(const Macros ¯os);
|
||||
static QByteArray toByteArray(const QVector<Macros> ¯oss);
|
||||
|
||||
static Macros toMacros(const QByteArray &text);
|
||||
|
||||
// define Foo will be converted to Foo=1
|
||||
static Macro fromKeyValue(const QString &utf16text);
|
||||
static Macro fromKeyValue(const QByteArray &text);
|
||||
QByteArray toKeyValue(const QByteArray &prefix) const;
|
||||
|
||||
public:
|
||||
QByteArray key;
|
||||
QByteArray value;
|
||||
MacroType type = MacroType::Invalid;
|
||||
|
||||
private:
|
||||
static QList<QByteArray> splitLines(const QByteArray &text);
|
||||
static QByteArray removeNonsemanticSpaces(QByteArray line);
|
||||
static QList<QByteArray> tokenizeLine(const QByteArray &line);
|
||||
static QList<QList<QByteArray>> tokenizeLines(const QList<QByteArray> &lines);
|
||||
static Macro tokensToMacro(const QList<QByteArray> &tokens);
|
||||
static Macros tokensLinesToMacros(const QList<QList<QByteArray>> &tokensLines);
|
||||
};
|
||||
|
||||
inline
|
||||
uint qHash(const Macro ¯o)
|
||||
{
|
||||
using ::qHash;
|
||||
return qHash(macro.key) ^ qHash(macro.value) ^ qHash(int(macro.type));
|
||||
}
|
||||
|
||||
inline
|
||||
bool operator==(const Macro &first, const Macro &second)
|
||||
{
|
||||
return first.type == second.type
|
||||
&& first.key == second.key
|
||||
&& first.value == second.value;
|
||||
}
|
||||
|
||||
} // namespace ProjectExplorer
|
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "projectexplorer_export.h"
|
||||
#include "projectexplorer_global.h"
|
||||
#include "projectmacro.h"
|
||||
|
||||
#include <coreplugin/id.h>
|
||||
|
||||
@@ -122,9 +123,9 @@ public:
|
||||
virtual WarningFlags warningFlags(const QStringList &cflags) const = 0;
|
||||
|
||||
// A PredefinedMacrosRunner is created in the ui thread and runs in another thread.
|
||||
using PredefinedMacrosRunner = std::function<QByteArray(const QStringList &cxxflags)>;
|
||||
using PredefinedMacrosRunner = std::function<Macros(const QStringList &cxxflags)>;
|
||||
virtual PredefinedMacrosRunner createPredefinedMacrosRunner() const = 0;
|
||||
virtual QByteArray predefinedMacros(const QStringList &cxxflags) const = 0;
|
||||
virtual Macros predefinedMacros(const QStringList &cxxflags) const = 0;
|
||||
|
||||
// A SystemHeaderPathsRunner is created in the ui thread and runs in another thread.
|
||||
using SystemHeaderPathsRunner = std::function<QList<HeaderPath>(const QStringList &cxxflags, const QString &sysRoot)>;
|
||||
|
@@ -492,7 +492,7 @@ public:
|
||||
Abi targetAbi() const override { return Abi::hostAbi(); }
|
||||
bool isValid() const override { return m_valid; }
|
||||
PredefinedMacrosRunner createPredefinedMacrosRunner() const override { return PredefinedMacrosRunner(); }
|
||||
QByteArray predefinedMacros(const QStringList &cxxflags) const override { Q_UNUSED(cxxflags); return QByteArray(); }
|
||||
Macros predefinedMacros(const QStringList &cxxflags) const override { Q_UNUSED(cxxflags); return Macros(); }
|
||||
CompilerFlags compilerFlags(const QStringList &cxxflags) const override { Q_UNUSED(cxxflags); return NoFlags; }
|
||||
WarningFlags warningFlags(const QStringList &cflags) const override { Q_UNUSED(cflags); return WarningFlags::NoWarnings; }
|
||||
SystemHeaderPathsRunner createSystemHeaderPathsRunner() const override { return SystemHeaderPathsRunner(); }
|
||||
|
@@ -975,17 +975,7 @@ void QbsProject::updateCppCodeModel()
|
||||
QStringList list = props.getModulePropertiesAsStringList(
|
||||
QLatin1String(CONFIG_CPP_MODULE),
|
||||
QLatin1String(CONFIG_DEFINES));
|
||||
QByteArray grpDefines;
|
||||
foreach (const QString &def, list) {
|
||||
QByteArray data = def.toUtf8();
|
||||
int pos = data.indexOf('=');
|
||||
if (pos >= 0)
|
||||
data[pos] = ' ';
|
||||
else
|
||||
data.append(" 1"); // cpp.defines: [ "FOO" ] is considered to be "FOO=1"
|
||||
grpDefines += (QByteArray("#define ") + data + '\n');
|
||||
}
|
||||
rpp.setDefines(grpDefines);
|
||||
rpp.setMacros(Utils::transform<QVector>(list, [](const QString &s) { return ProjectExplorer::Macro::fromKeyValue(s); }));
|
||||
|
||||
list = props.getModulePropertiesAsStringList(QLatin1String(CONFIG_CPP_MODULE),
|
||||
QLatin1String(CONFIG_INCLUDEPATHS));
|
||||
|
@@ -292,7 +292,7 @@ void QmakeProject::updateCppCodeModel()
|
||||
rpp.setBuildSystemTarget(pro->targetInformation().target);
|
||||
// TODO: Handle QMAKE_CFLAGS
|
||||
rpp.setFlagsForCxx({cxxToolChain, pro->variableValue(Variable::CppFlags)});
|
||||
rpp.setDefines(pro->cxxDefines());
|
||||
rpp.setMacros(ProjectExplorer::Macro::toMacros(pro->cxxDefines()));
|
||||
rpp.setPreCompiledHeaders(pro->variableValue(Variable::PrecompiledHeader));
|
||||
rpp.setSelectedForBuilding(pro->includedInExactParse());
|
||||
|
||||
|
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <projectexplorer/headerpath.h>
|
||||
#include <projectexplorer/abi.h>
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
#include <coreplugin/id.h>
|
||||
|
||||
#include <functional>
|
||||
@@ -59,7 +60,7 @@ public:
|
||||
using SystemHeaderPathsRunner = std::function<QList<HeaderPath>(const QStringList &cxxflags, const QString &sysRoot)>;
|
||||
virtual SystemHeaderPathsRunner createSystemHeaderPathsRunner() const { return SystemHeaderPathsRunner(); }
|
||||
|
||||
using PredefinedMacrosRunner = std::function<QByteArray(const QStringList &cxxflags)>;
|
||||
using PredefinedMacrosRunner = std::function<Macros(const QStringList &cxxflags)>;
|
||||
virtual PredefinedMacrosRunner createPredefinedMacrosRunner() const { return PredefinedMacrosRunner(); }
|
||||
|
||||
virtual QString originalTargetTriple() const { return QString(); }
|
||||
|
@@ -7,13 +7,13 @@ include($$PWD/../../../src/libs/utils/utils-lib.pri)
|
||||
include($$PWD/../../../src/libs/sqlite/sqlite-lib.pri)
|
||||
include($$PWD/../../../src/libs/clangsupport/clangsupport-lib.pri)
|
||||
include($$PWD/../../../src/plugins/coreplugin/corepluginunittestfiles.pri)
|
||||
include($$PWD/../../../src/plugins/projectexplorer/projectexplorerunittestfiles.pri)
|
||||
include($$PWD/../../../src/tools/clangrefactoringbackend/source/clangrefactoringbackend-source.pri)
|
||||
include($$PWD/../../../src/tools/clangpchmanagerbackend/source/clangpchmanagerbackend-source.pri)
|
||||
include($$PWD/../../../src/plugins/clangrefactoring/clangrefactoring-source.pri)
|
||||
include($$PWD/../../../src/plugins/clangpchmanager/clangpchmanager-source.pri)
|
||||
include($$PWD/../../../src/plugins/cpptools/cpptoolsunittestfiles.pri)
|
||||
include(cplusplus.pri)
|
||||
|
||||
!isEmpty(LLVM_INSTALL_DIR) {
|
||||
include($$PWD/../../../src/shared/clang/clang_defines.pri)
|
||||
include($$PWD/../../../src/tools/clangbackend/ipcsource/clangbackendclangipc-source.pri)
|
||||
|
@@ -43,4 +43,5 @@ using testing::Property;
|
||||
using testing::Return;
|
||||
using testing::ReturnRef;
|
||||
using testing::Sequence;
|
||||
using testing::StrEq;
|
||||
using testing::UnorderedElementsAre;
|
||||
|
@@ -29,6 +29,8 @@
|
||||
|
||||
#include <coreplugin/find/searchresultitem.h>
|
||||
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
|
||||
namespace Core {
|
||||
namespace Search {
|
||||
|
||||
@@ -54,3 +56,35 @@ void PrintTo(const TextRange &range, ::std::ostream *os)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
static const char *typeToString(const MacroType &type)
|
||||
{
|
||||
switch (type) {
|
||||
case MacroType::Invalid: return "MacroType::Invalid";
|
||||
case MacroType::Define: return "MacroType::Define";
|
||||
case MacroType::Undefine: return "MacroType::Undefine";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const MacroType &type)
|
||||
{
|
||||
out << typeToString(type);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const Macro ¯o)
|
||||
{
|
||||
out << "("
|
||||
<< macro.key.data() << ", "
|
||||
<< macro.value.data() << ", "
|
||||
<< macro.type << ")";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -42,3 +42,13 @@ void PrintTo(const TextRange &range, ::std::ostream *os);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace ProjectExplorer {
|
||||
|
||||
enum class MacroType;
|
||||
class Macro;
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const MacroType &type);
|
||||
std::ostream &operator<<(std::ostream &out, const Macro ¯o);
|
||||
|
||||
}
|
||||
|
408
tests/unit/unittest/projectmacro-test.cpp
Normal file
408
tests/unit/unittest/projectmacro-test.cpp
Normal file
@@ -0,0 +1,408 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 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"
|
||||
|
||||
#define private public
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
#undef private
|
||||
|
||||
namespace {
|
||||
|
||||
using ProjectExplorer::MacroType;
|
||||
using ProjectExplorer::Macro;
|
||||
using ProjectExplorer::Macros;
|
||||
|
||||
MATCHER_P3(IsMacro, key, value, type,
|
||||
std::string(negation ? "isn't" : "is")
|
||||
+ " key "+ PrintToString(key)
|
||||
+ ", value " + PrintToString(value)
|
||||
+ " and type " + PrintToString(type))
|
||||
{
|
||||
return arg.key == key && arg.value == value && arg.type == type;
|
||||
}
|
||||
|
||||
TEST(Macro, SplitLines)
|
||||
{
|
||||
QByteArray text = "#define Foo 42\n\n#define Bar\n#define HoHoHo Bar\n// foo";
|
||||
|
||||
auto textLines = Macro::splitLines(text);
|
||||
|
||||
ASSERT_THAT(textLines, ElementsAre("#define Foo 42", "#define Bar", "#define HoHoHo Bar", "// foo"));
|
||||
}
|
||||
|
||||
TEST(Macro, RemoveCarriageReturn)
|
||||
{
|
||||
QByteArray text = "#define Foo 42\r\n#define Bar\n";
|
||||
|
||||
auto textLines = Macro::splitLines(text);
|
||||
|
||||
ASSERT_THAT(textLines, ElementsAre("#define Foo 42", "#define Bar"));
|
||||
}
|
||||
|
||||
TEST(Macro, TokenizeNullLine)
|
||||
{
|
||||
QByteArray line;
|
||||
|
||||
auto tokens = Macro::tokenizeLine(line);
|
||||
|
||||
ASSERT_THAT(tokens, IsEmpty());
|
||||
}
|
||||
|
||||
TEST(Macro, TokenizeEmptyLine)
|
||||
{
|
||||
QByteArray line = "";
|
||||
|
||||
auto tokens = Macro::tokenizeLine(line);
|
||||
|
||||
ASSERT_THAT(tokens, IsEmpty());
|
||||
}
|
||||
|
||||
TEST(Macro, TokenizeSpaces)
|
||||
{
|
||||
QByteArray line = " ";
|
||||
|
||||
auto tokens = Macro::tokenizeLine(line);
|
||||
|
||||
ASSERT_THAT(tokens, IsEmpty());
|
||||
}
|
||||
|
||||
TEST(Macro, TokenizeOneEntry)
|
||||
{
|
||||
QByteArray line = "//blah";
|
||||
|
||||
auto tokens = Macro::tokenizeLine(line);
|
||||
|
||||
ASSERT_THAT(tokens, IsEmpty());
|
||||
}
|
||||
|
||||
TEST(Macro, TokenizeThreeEntries)
|
||||
{
|
||||
QByteArray line = "#define Foo 42";
|
||||
|
||||
auto tokens = Macro::tokenizeLine(line);
|
||||
|
||||
ASSERT_THAT(tokens, ElementsAre("#define", "Foo", "42"));
|
||||
}
|
||||
|
||||
TEST(Macro, TokenizeManyEntries)
|
||||
{
|
||||
QByteArray line = "#define Foo unsigned long long int";
|
||||
|
||||
auto tokens = Macro::tokenizeLine(line);
|
||||
|
||||
ASSERT_THAT(tokens, ElementsAre("#define", "Foo", "unsigned long long int"));
|
||||
}
|
||||
|
||||
TEST(Macro, TokenizeWithMutipleSpaces)
|
||||
{
|
||||
QByteArray line = "#define Foo 42";
|
||||
|
||||
auto tokens = Macro::tokenizeLine(line);
|
||||
|
||||
ASSERT_THAT(tokens, ElementsAre("#define", "Foo", "42"));
|
||||
}
|
||||
|
||||
TEST(Macro, TokenizeLines)
|
||||
{
|
||||
QList<QByteArray> lines = {"#define Foo 42",
|
||||
"#define Bar Ho",
|
||||
"// this is a comment",
|
||||
" "};
|
||||
|
||||
auto tokensLines = Macro::tokenizeLines(lines);
|
||||
|
||||
ASSERT_THAT(tokensLines,
|
||||
ElementsAre(ElementsAre("#define", "Foo", "42"),
|
||||
ElementsAre("#define", "Bar", "Ho"),
|
||||
ElementsAre("//", "this", "is a comment"),
|
||||
IsEmpty()));
|
||||
}
|
||||
|
||||
TEST(Macro, SpacesBeforEntries)
|
||||
{
|
||||
QByteArray line = " #define Foo";
|
||||
|
||||
auto strippedLine = Macro::removeNonsemanticSpaces(line);
|
||||
|
||||
ASSERT_THAT(strippedLine, "#define Foo");
|
||||
}
|
||||
|
||||
TEST(Macro, SpacesAfterEntries)
|
||||
{
|
||||
QByteArray line = "#define Foo ";
|
||||
|
||||
auto strippedLine = Macro::removeNonsemanticSpaces(line);
|
||||
|
||||
ASSERT_THAT(strippedLine, "#define Foo");
|
||||
}
|
||||
|
||||
TEST(Macro, ManySpacesInbetweenEntries)
|
||||
{
|
||||
QByteArray line = "#define \t Foo 42";
|
||||
|
||||
auto strippedLine = Macro::removeNonsemanticSpaces(line);
|
||||
|
||||
ASSERT_THAT(strippedLine, "#define Foo 42");
|
||||
}
|
||||
|
||||
TEST(Macro, EmptyString)
|
||||
{
|
||||
QByteArray line = "#define \t Foo \"\"";
|
||||
|
||||
auto strippedLine = Macro::removeNonsemanticSpaces(line);
|
||||
|
||||
ASSERT_THAT(strippedLine, "#define Foo \"\"");
|
||||
}
|
||||
|
||||
TEST(Macro, StringWithQuotes)
|
||||
{
|
||||
QByteArray line = "#define \t Foo \"\\\"string\\\"\"";
|
||||
|
||||
auto strippedLine = Macro::removeNonsemanticSpaces(line);
|
||||
|
||||
ASSERT_THAT(strippedLine, "#define Foo \"\\\"string\\\"\"");
|
||||
}
|
||||
|
||||
TEST(Macro, DISABLED_StringConcatenation)
|
||||
{
|
||||
QByteArray line = "#define \t Foo \"a\" \"b\"";
|
||||
|
||||
auto strippedLine = Macro::removeNonsemanticSpaces(line);
|
||||
|
||||
ASSERT_THAT(strippedLine, "#define Foo \"a\" \"b\"");
|
||||
}
|
||||
|
||||
TEST(Macro, DISABLED_TokenConcatenation)
|
||||
{
|
||||
QByteArray line = "#define \t Foo \"a\" ## c";
|
||||
|
||||
auto strippedLine = Macro::removeNonsemanticSpaces(line);
|
||||
|
||||
ASSERT_THAT(strippedLine, "#define Foo \"a\" ## c");
|
||||
}
|
||||
|
||||
TEST(Macro, StringWithQuotesAndSpaces)
|
||||
{
|
||||
QByteArray line = "#define \t Foo \"\\\"string \\\"\"";
|
||||
|
||||
auto strippedLine = Macro::removeNonsemanticSpaces(line);
|
||||
|
||||
ASSERT_THAT(strippedLine.toStdString(), "#define Foo \"\\\"string \\\"\"");
|
||||
}
|
||||
|
||||
TEST(Macro, SpacesAferHashEntries)
|
||||
{
|
||||
QByteArray line = "# define Foo 42";
|
||||
|
||||
auto strippedLine = Macro::removeNonsemanticSpaces(line);
|
||||
|
||||
ASSERT_THAT(strippedLine, "#define Foo 42");
|
||||
}
|
||||
|
||||
TEST(Macro, SpacesInStringEntries)
|
||||
{
|
||||
QByteArray line = "#define Foo \"some text with spaces\"";
|
||||
|
||||
auto strippedLine = Macro::removeNonsemanticSpaces(line);
|
||||
|
||||
ASSERT_THAT(strippedLine, "#define Foo \"some text with spaces\"");
|
||||
}
|
||||
|
||||
TEST(Macro, EmptyTokensToMacro)
|
||||
{
|
||||
QList<QByteArray> tokens;
|
||||
|
||||
auto macro = Macro::tokensToMacro(tokens);
|
||||
|
||||
ASSERT_THAT(macro, IsMacro("", "", MacroType::Invalid));
|
||||
}
|
||||
|
||||
TEST(Macro, DefineTwoTokensToMacro)
|
||||
{
|
||||
QList<QByteArray> tokens = {"#define", "Foo"};
|
||||
|
||||
auto macro = Macro::tokensToMacro(tokens);
|
||||
|
||||
ASSERT_THAT(macro, IsMacro("Foo", "", MacroType::Define));
|
||||
}
|
||||
|
||||
TEST(Macro, DefineThreeTokensToMacro)
|
||||
{
|
||||
QList<QByteArray> tokens = {"#define", "Foo", "42"};
|
||||
|
||||
auto macro = Macro::tokensToMacro(tokens);
|
||||
|
||||
ASSERT_THAT(macro, IsMacro("Foo", "42", MacroType::Define));
|
||||
}
|
||||
|
||||
TEST(Macro, DoNotParseNonDefines)
|
||||
{
|
||||
QList<QByteArray> tokens = {"//", "this", "is a comment"};
|
||||
|
||||
auto macro = Macro::tokensToMacro(tokens);
|
||||
|
||||
ASSERT_THAT(macro, IsMacro("", "", MacroType::Invalid));
|
||||
}
|
||||
|
||||
TEST(Macro, TokensLinesToMacros)
|
||||
{
|
||||
QList<QList<QByteArray>> tokensLines = {{"#define", "Foo", "42"},
|
||||
{"#define", "Bar", "Ho"},
|
||||
{"//", "this", "is", "a", "comment"},
|
||||
{}};
|
||||
|
||||
auto macros = Macro::tokensLinesToMacros(tokensLines);
|
||||
|
||||
ASSERT_THAT(macros, ElementsAre(IsMacro("Foo", "42", MacroType::Define),
|
||||
IsMacro("Bar", "Ho", MacroType::Define)));
|
||||
}
|
||||
|
||||
|
||||
TEST(Macro, TextToMacros)
|
||||
{
|
||||
QByteArray text = {"#define Foo 42\n"
|
||||
"#define Bar Ho\n"
|
||||
"// this is a comment\n"
|
||||
" "};
|
||||
|
||||
auto macros = Macro::toMacros(text);
|
||||
|
||||
ASSERT_THAT(macros, ElementsAre(IsMacro("Foo", "42", MacroType::Define),
|
||||
IsMacro("Bar", "Ho", MacroType::Define)));
|
||||
}
|
||||
|
||||
TEST(Macro, InvalidToText)
|
||||
{
|
||||
Macro macro;
|
||||
|
||||
auto text = macro.toByteArray();
|
||||
|
||||
ASSERT_THAT(text, QByteArray());
|
||||
}
|
||||
|
||||
TEST(Macro, DefineToText)
|
||||
{
|
||||
Macro macro{"Foo", "Bar", MacroType::Define};
|
||||
|
||||
auto text = macro.toByteArray();
|
||||
|
||||
ASSERT_THAT(text, "#define Foo Bar");
|
||||
}
|
||||
|
||||
TEST(Macro, DefineWithSpacesToText)
|
||||
{
|
||||
Macro macro{"LongInt", "long long int", MacroType::Define};
|
||||
|
||||
auto text = macro.toByteArray();
|
||||
|
||||
ASSERT_THAT(text, "#define LongInt long long int");
|
||||
}
|
||||
|
||||
TEST(Macro, UndefineToText)
|
||||
{
|
||||
Macro macro{"Foo", "Bar", MacroType::Undefine};
|
||||
|
||||
auto text = macro.toByteArray();
|
||||
|
||||
ASSERT_THAT(text, "#undef Foo");
|
||||
}
|
||||
|
||||
TEST(Macro, MacrosToText)
|
||||
{
|
||||
Macros macros{{"LongInt", "long long int"}, {"Foo", "Bar"}, {}};
|
||||
|
||||
auto text = Macro::toByteArray(macros);
|
||||
|
||||
ASSERT_THAT(text, "#define LongInt long long int\n#define Foo Bar\n");
|
||||
}
|
||||
|
||||
TEST(Macro, MacrosVectorToText)
|
||||
{
|
||||
Macros macros{{"LongInt", "long long int"}, {"Foo", "Bar"}, {}, {"Foo", MacroType::Undefine}};
|
||||
|
||||
auto text = Macro::toByteArray(macros);
|
||||
|
||||
ASSERT_THAT(text, "#define LongInt long long int\n#define Foo Bar\n#undef Foo\n");
|
||||
}
|
||||
|
||||
TEST(Macro, EmptyKeyValueToMacro)
|
||||
{
|
||||
QString text;
|
||||
|
||||
auto macro = Macro::fromKeyValue(text);
|
||||
|
||||
ASSERT_THAT(macro, IsMacro("", "", MacroType::Invalid));
|
||||
}
|
||||
|
||||
TEST(Macro, KeyToMacro)
|
||||
{
|
||||
QString text = "Foo";
|
||||
|
||||
auto macro = Macro::fromKeyValue(text);
|
||||
|
||||
ASSERT_THAT(macro, IsMacro("Foo", "1", MacroType::Define));
|
||||
}
|
||||
|
||||
TEST(Macro, KeyValueToMacro)
|
||||
{
|
||||
QString text = "Foo=\"Some=Text\"";
|
||||
|
||||
auto macro = Macro::fromKeyValue(text);
|
||||
|
||||
ASSERT_THAT(macro, IsMacro("Foo", "\"Some=Text\"", MacroType::Define));
|
||||
}
|
||||
|
||||
TEST(Macro, InvalidMacroToKeyValue)
|
||||
{
|
||||
Macro macro;
|
||||
QByteArray prefix = "-D";
|
||||
|
||||
auto keyValue = macro.toKeyValue(prefix);
|
||||
|
||||
ASSERT_THAT(keyValue, "");
|
||||
}
|
||||
|
||||
TEST(Macro, DefineKeyOnlyMacroToKeyValue)
|
||||
{
|
||||
Macro macro{"Foo"};
|
||||
QByteArray prefix = "-D";
|
||||
|
||||
auto keyValue = macro.toKeyValue(prefix);
|
||||
|
||||
ASSERT_THAT(keyValue, "-DFoo");
|
||||
}
|
||||
|
||||
TEST(Macro, DefineMacroToKeyValue)
|
||||
{
|
||||
Macro macro{"Foo", "Bar"};
|
||||
QByteArray prefix = "-D";
|
||||
|
||||
auto keyValue = macro.toKeyValue(prefix);
|
||||
|
||||
ASSERT_THAT(keyValue, "-DFoo=Bar");
|
||||
}
|
||||
}
|
||||
|
@@ -37,7 +37,6 @@ DEFINES += CPPTOOLS_JSON=\"R\\\"xxx($${cpptoolsjson.output})xxx\\\"\"
|
||||
|
||||
SOURCES += \
|
||||
changedfilepathcompressor-test.cpp \
|
||||
clangfollowsymbol-test.cpp \
|
||||
clangpathwatcher-test.cpp \
|
||||
clangqueryexamplehighlightmarker-test.cpp \
|
||||
clangqueryhighlightmarker-test.cpp \
|
||||
@@ -59,6 +58,7 @@ SOURCES += \
|
||||
pchmanagerclient-test.cpp \
|
||||
pchmanagerserver-test.cpp \
|
||||
processevents-utilities.cpp \
|
||||
projectmacro-test.cpp \
|
||||
projectparts-test.cpp \
|
||||
projectupdater-test.cpp \
|
||||
readandwritemessageblock-test.cpp \
|
||||
@@ -96,6 +96,7 @@ SOURCES += \
|
||||
clangdocumentsuspenderresumer-test.cpp \
|
||||
clangdocument-test.cpp \
|
||||
clangfixitoperation-test.cpp \
|
||||
clangfollowsymbol-test.cpp \
|
||||
clangisdiagnosticrelatedtolocation-test.cpp \
|
||||
clangjobqueue-test.cpp \
|
||||
clangjobs-test.cpp \
|
||||
|
Reference in New Issue
Block a user