forked from qt-creator/qt-creator
CMake: Extract crossReferences data of targets in server-mode
Use the information to add a filenode below a target that takes you directly to the target definition. Change-Id: Ifcb8e2c4f085110033019ea3816c79f5b8630472 Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
@@ -56,7 +56,10 @@ const char CONFIGURE_TYPE[] = "configure";
|
||||
const char CMAKE_INPUTS_TYPE[] = "cmakeInputs";
|
||||
const char COMPUTE_TYPE[] = "compute";
|
||||
|
||||
const char BACKTRACE_KEY[] = "backtrace";
|
||||
const char LINE_KEY[] = "line";
|
||||
const char NAME_KEY[] = "name";
|
||||
const char PATH_KEY[] = "path";
|
||||
const char SOURCE_DIRECTORY_KEY[] = "sourceDirectory";
|
||||
const char SOURCES_KEY[] = "sources";
|
||||
|
||||
@@ -484,6 +487,8 @@ ServerModeReader::Target *ServerModeReader::extractTargetData(const QVariantMap
|
||||
target->sourceDirectory = FileName::fromString(data.value(SOURCE_DIRECTORY_KEY).toString());
|
||||
target->buildDirectory = FileName::fromString(data.value("buildDirectory").toString());
|
||||
|
||||
target->crossReferences = extractCrossReferences(data.value("crossReferences").toMap());
|
||||
|
||||
QDir srcDir(target->sourceDirectory.toString());
|
||||
|
||||
target->type = data.value("type").toString();
|
||||
@@ -528,6 +533,72 @@ ServerModeReader::FileGroup *ServerModeReader::extractFileGroupData(const QVaria
|
||||
return fileGroup;
|
||||
}
|
||||
|
||||
QList<ServerModeReader::CrossReference *> ServerModeReader::extractCrossReferences(const QVariantMap &data)
|
||||
{
|
||||
QList<CrossReference *> crossReferences;
|
||||
|
||||
if (data.isEmpty())
|
||||
return crossReferences;
|
||||
|
||||
auto cr = std::make_unique<CrossReference>();
|
||||
cr->backtrace = extractBacktrace(data.value(BACKTRACE_KEY, QVariantList()).toList());
|
||||
QTC_ASSERT(!cr->backtrace.isEmpty(), return {});
|
||||
crossReferences.append(cr.release());
|
||||
|
||||
const QVariantList related = data.value("relatedStatements", QVariantList()).toList();
|
||||
for (const QVariant &relatedData : related) {
|
||||
auto cr = std::make_unique<CrossReference>();
|
||||
|
||||
// extract information:
|
||||
const QVariantMap map = relatedData.toMap();
|
||||
const QString typeString = map.value("type", QString()).toString();
|
||||
if (typeString.isEmpty())
|
||||
cr->type = CrossReference::TARGET;
|
||||
else if (typeString == "target_link_libraries")
|
||||
cr->type = CrossReference::LIBRARIES;
|
||||
else if (typeString == "target_compile_defines")
|
||||
cr->type = CrossReference::DEFINES;
|
||||
else if (typeString == "target_include_directories")
|
||||
cr->type = CrossReference::INCLUDES;
|
||||
else
|
||||
cr->type = CrossReference::UNKNOWN;
|
||||
cr->backtrace = extractBacktrace(map.value(BACKTRACE_KEY, QVariantList()).toList());
|
||||
|
||||
// sanity check:
|
||||
if (cr->backtrace.isEmpty())
|
||||
continue;
|
||||
|
||||
// store information:
|
||||
crossReferences.append(cr.release());
|
||||
}
|
||||
return crossReferences;
|
||||
}
|
||||
|
||||
ServerModeReader::BacktraceItem *ServerModeReader::extractBacktraceItem(const QVariantMap &data)
|
||||
{
|
||||
QTC_ASSERT(!data.isEmpty(), return nullptr);
|
||||
auto item = std::make_unique<BacktraceItem>();
|
||||
|
||||
item->line = data.value(LINE_KEY, -1).toInt();
|
||||
item->name = data.value(NAME_KEY, QString()).toString();
|
||||
item->path = data.value(PATH_KEY, QString()).toString();
|
||||
|
||||
QTC_ASSERT(!item->path.isEmpty(), return nullptr);
|
||||
return item.release();
|
||||
}
|
||||
|
||||
QList<ServerModeReader::BacktraceItem *> ServerModeReader::extractBacktrace(const QVariantList &data)
|
||||
{
|
||||
QList<BacktraceItem *> btResult;
|
||||
for (const QVariant &bt : data) {
|
||||
BacktraceItem *btItem = extractBacktraceItem(bt.toMap());
|
||||
QTC_ASSERT(btItem, continue);
|
||||
|
||||
btResult.append(btItem);
|
||||
}
|
||||
return btResult;
|
||||
}
|
||||
|
||||
void ServerModeReader::extractCMakeInputsData(const QVariantMap &data)
|
||||
{
|
||||
const FileName src = FileName::fromString(data.value(SOURCE_DIRECTORY_KEY).toString());
|
||||
@@ -699,6 +770,36 @@ void ServerModeReader::addTargets(const QHash<Utils::FileName, ProjectExplorer::
|
||||
CMakeTargetNode *tNode = createTargetNode(cmakeListsNodes, t->sourceDirectory, t->name);
|
||||
QTC_ASSERT(tNode, qDebug() << "No target node for" << t->sourceDirectory << t->name; continue);
|
||||
tNode->setTargetInformation(t->artifacts, t->type);
|
||||
QList<FolderNode::LocationInfo> info;
|
||||
// Set up a default target path:
|
||||
FileName targetPath = t->sourceDirectory;
|
||||
targetPath.appendPath("CMakeLists.txt");
|
||||
for (CrossReference *cr : Utils::asConst(t->crossReferences)) {
|
||||
BacktraceItem *bt = cr->backtrace.isEmpty() ? nullptr : cr->backtrace.at(0);
|
||||
if (bt) {
|
||||
const QString btName = bt->name.toLower();
|
||||
const FileName path = Utils::FileName::fromUserInput(bt->path);
|
||||
QString dn;
|
||||
if (cr->type != CrossReference::TARGET) {
|
||||
if (path == targetPath) {
|
||||
if (bt->line >= 0)
|
||||
dn = tr("%1 in line %3").arg(btName).arg(bt->line);
|
||||
else
|
||||
dn = tr("%1").arg(btName);
|
||||
} else {
|
||||
if (bt->line >= 0)
|
||||
dn = tr("%1 in %2:%3").arg(btName, path.toUserOutput()).arg(bt->line);
|
||||
else
|
||||
dn = tr("%1 in %2").arg(btName, path.toUserOutput());
|
||||
}
|
||||
} else {
|
||||
dn = tr("Target Definition");
|
||||
targetPath = path;
|
||||
}
|
||||
info.append(FolderNode::LocationInfo(dn, path, bt->line));
|
||||
}
|
||||
}
|
||||
tNode->setLocationInfo(info);
|
||||
addFileGroups(tNode, t->sourceDirectory, t->buildDirectory, t->fileGroups, knownHeaderNodes);
|
||||
}
|
||||
}
|
||||
|
@@ -29,6 +29,8 @@
|
||||
#include "servermode.h"
|
||||
#include "cmakeparser.h"
|
||||
|
||||
#include <QList>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace CMakeProjectManager {
|
||||
@@ -87,8 +89,26 @@ private:
|
||||
bool isGenerated;
|
||||
};
|
||||
|
||||
struct BacktraceItem {
|
||||
int line = -1;
|
||||
QString path;
|
||||
QString name;
|
||||
};
|
||||
|
||||
struct CrossReference {
|
||||
~CrossReference() { qDeleteAll(backtrace); backtrace.clear(); }
|
||||
QList<BacktraceItem *> backtrace;
|
||||
enum Type { TARGET, LIBRARIES, DEFINES, INCLUDES, UNKNOWN };
|
||||
Type type;
|
||||
};
|
||||
|
||||
struct Target {
|
||||
~Target() { qDeleteAll(fileGroups); fileGroups.clear(); }
|
||||
~Target() {
|
||||
qDeleteAll(fileGroups);
|
||||
fileGroups.clear();
|
||||
qDeleteAll(crossReferences);
|
||||
crossReferences.clear();
|
||||
}
|
||||
|
||||
Project *project = nullptr;
|
||||
QString name;
|
||||
@@ -97,6 +117,7 @@ private:
|
||||
Utils::FileName sourceDirectory;
|
||||
Utils::FileName buildDirectory;
|
||||
QList<FileGroup *> fileGroups;
|
||||
QList<CrossReference *> crossReferences;
|
||||
};
|
||||
|
||||
struct Project {
|
||||
@@ -111,6 +132,9 @@ private:
|
||||
Project *extractProjectData(const QVariantMap &data, QSet<QString> &knownTargets);
|
||||
Target *extractTargetData(const QVariantMap &data, Project *p, QSet<QString> &knownTargets);
|
||||
FileGroup *extractFileGroupData(const QVariantMap &data, const QDir &srcDir, Target *t);
|
||||
QList<CrossReference *> extractCrossReferences(const QVariantMap &data);
|
||||
QList<BacktraceItem *> extractBacktrace(const QVariantList &data);
|
||||
BacktraceItem *extractBacktraceItem(const QVariantMap &data);
|
||||
void extractCMakeInputsData(const QVariantMap &data);
|
||||
void extractCacheData(const QVariantMap &data);
|
||||
|
||||
|
Reference in New Issue
Block a user