forked from qt-creator/qt-creator
CMake: Extract and show more CMake location information for targets
Report more cmake file locations that are relevant to a target in the "Open..." menu entry in the target's context menu. This information is extracted from the backtrace information that is provided by fileapi. Change-Id: I01659a6cc7254cd0ef6b533a0785d2f15d31c3c6 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io> Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -368,8 +368,10 @@ QList<CMakeBuildTarget> BuildDirManager::takeBuildTargets(QString &errorMessage)
|
|||||||
|
|
||||||
// Guess at the target definition position when no details are known
|
// Guess at the target definition position when no details are known
|
||||||
for (CMakeBuildTarget &t : readerTargets) {
|
for (CMakeBuildTarget &t : readerTargets) {
|
||||||
if (t.definitionFile.isEmpty()) {
|
if (t.backtrace.isEmpty()) {
|
||||||
t.definitionFile = t.sourceDirectory.pathAppended("CMakeLists.txt");
|
t.backtrace.append(
|
||||||
|
FolderNode::LocationInfo(tr("CMakeLists.txt in source directory"),
|
||||||
|
t.sourceDirectory.pathAppended("CMakeLists.txt")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.append(readerTargets);
|
result.append(readerTargets);
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
#include "cmake_global.h"
|
#include "cmake_global.h"
|
||||||
|
|
||||||
#include <projectexplorer/projectmacro.h>
|
#include <projectexplorer/projectmacro.h>
|
||||||
|
#include <projectexplorer/projectnodes.h>
|
||||||
|
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
@@ -43,6 +44,9 @@ enum TargetType {
|
|||||||
UtilityType
|
UtilityType
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using Backtrace = QVector<ProjectExplorer::FolderNode::LocationInfo>;
|
||||||
|
using Backtraces = QVector<Backtrace>;
|
||||||
|
|
||||||
class CMAKE_EXPORT CMakeBuildTarget
|
class CMAKE_EXPORT CMakeBuildTarget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -53,8 +57,13 @@ public:
|
|||||||
Utils::FilePath sourceDirectory;
|
Utils::FilePath sourceDirectory;
|
||||||
Utils::FilePath makeCommand;
|
Utils::FilePath makeCommand;
|
||||||
|
|
||||||
Utils::FilePath definitionFile;
|
Backtrace backtrace;
|
||||||
int definitionLine = -1;
|
|
||||||
|
Backtraces dependencyDefinitions;
|
||||||
|
Backtraces sourceDefinitions;
|
||||||
|
Backtraces defineDefinitions;
|
||||||
|
Backtraces includeDefinitions;
|
||||||
|
Backtraces installDefinitions;
|
||||||
|
|
||||||
// code model
|
// code model
|
||||||
QList<Utils::FilePath> includeFiles;
|
QList<Utils::FilePath> includeFiles;
|
||||||
|
@@ -75,12 +75,13 @@ void CMakeTargetLocatorFilter::prepareSearch(const QString &entry)
|
|||||||
for (const CMakeBuildTarget &target : buildTargets) {
|
for (const CMakeBuildTarget &target : buildTargets) {
|
||||||
const int index = target.title.indexOf(entry);
|
const int index = target.title.indexOf(entry);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
const FilePath path = target.definitionFile.isEmpty()
|
const FilePath path = target.backtrace.isEmpty() ? cmakeProject->projectFilePath()
|
||||||
? cmakeProject->projectFilePath()
|
: target.backtrace.first().path;
|
||||||
: target.definitionFile;
|
const int line = target.backtrace.isEmpty() ? -1 : target.backtrace.first().line;
|
||||||
|
|
||||||
QVariantMap extraData;
|
QVariantMap extraData;
|
||||||
extraData.insert("project", cmakeProject->projectFilePath().toString());
|
extraData.insert("project", cmakeProject->projectFilePath().toString());
|
||||||
extraData.insert("line", target.definitionLine);
|
extraData.insert("line", line);
|
||||||
extraData.insert("file", path.toString());
|
extraData.insert("file", path.toString());
|
||||||
|
|
||||||
Core::LocatorFilterEntry filterEntry(this, target.title, extraData);
|
Core::LocatorFilterEntry filterEntry(this, target.title, extraData);
|
||||||
|
@@ -165,6 +165,39 @@ PreprocessedData preprocess(FileApiData &data,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVector<FolderNode::LocationInfo> extractBacktraceInformation(const BacktraceInfo &backtraces,
|
||||||
|
const QDir &sourceDir,
|
||||||
|
int backtraceIndex,
|
||||||
|
unsigned int locationInfoPriority)
|
||||||
|
{
|
||||||
|
QVector<FolderNode::LocationInfo> info;
|
||||||
|
// Set up a default target path:
|
||||||
|
while (backtraceIndex != -1) {
|
||||||
|
const size_t bi = static_cast<size_t>(backtraceIndex);
|
||||||
|
QTC_ASSERT(bi < backtraces.nodes.size(), break);
|
||||||
|
const BacktraceNode &btNode = backtraces.nodes[bi];
|
||||||
|
backtraceIndex = btNode.parent; // advance to next node
|
||||||
|
|
||||||
|
const size_t fileIndex = static_cast<size_t>(btNode.file);
|
||||||
|
QTC_ASSERT(fileIndex < backtraces.files.size(), break);
|
||||||
|
const FilePath path = FilePath::fromString(
|
||||||
|
sourceDir.absoluteFilePath(backtraces.files[fileIndex]));
|
||||||
|
|
||||||
|
if (btNode.command < 0) {
|
||||||
|
// No command, skip: The file itself is already covered:-)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t commandIndex = static_cast<size_t>(btNode.command);
|
||||||
|
QTC_ASSERT(commandIndex < backtraces.commands.size(), break);
|
||||||
|
|
||||||
|
const QString command = backtraces.commands[commandIndex];
|
||||||
|
|
||||||
|
info.append(FolderNode::LocationInfo(command, path, btNode.line, locationInfoPriority));
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
QList<CMakeBuildTarget> generateBuildTargets(const PreprocessedData &input,
|
QList<CMakeBuildTarget> generateBuildTargets(const PreprocessedData &input,
|
||||||
const FilePath &sourceDirectory,
|
const FilePath &sourceDirectory,
|
||||||
const FilePath &buildDirectory)
|
const FilePath &buildDirectory)
|
||||||
@@ -198,15 +231,29 @@ QList<CMakeBuildTarget> generateBuildTargets(const PreprocessedData &input,
|
|||||||
ct.sourceDirectory = FilePath::fromString(
|
ct.sourceDirectory = FilePath::fromString(
|
||||||
QDir::cleanPath(sourceDir.absoluteFilePath(t.sourceDir.toString())));
|
QDir::cleanPath(sourceDir.absoluteFilePath(t.sourceDir.toString())));
|
||||||
|
|
||||||
if (t.backtrace >= 0) {
|
ct.backtrace = extractBacktraceInformation(t.backtraceGraph, sourceDir, t.backtrace, 0);
|
||||||
const BacktraceNode &node = t.backtraceGraph.nodes[static_cast<size_t>(t.backtrace)];
|
|
||||||
const int fileIndex = node.file;
|
for (const DependencyInfo &d : t.dependencies) {
|
||||||
if (fileIndex >= 0) {
|
ct.dependencyDefinitions.append(
|
||||||
ct.definitionFile = FilePath::fromString(
|
extractBacktraceInformation(t.backtraceGraph, sourceDir, d.backtrace, 100));
|
||||||
QDir::cleanPath(sourceDir.absoluteFilePath(
|
}
|
||||||
t.backtraceGraph.files[static_cast<size_t>(fileIndex)])));
|
for (const SourceInfo &si : t.sources) {
|
||||||
ct.definitionLine = node.line;
|
ct.sourceDefinitions.append(
|
||||||
|
extractBacktraceInformation(t.backtraceGraph, sourceDir, si.backtrace, 200));
|
||||||
|
}
|
||||||
|
for (const CompileInfo &ci : t.compileGroups) {
|
||||||
|
for (const IncludeInfo &ii : ci.includes) {
|
||||||
|
ct.includeDefinitions.append(
|
||||||
|
extractBacktraceInformation(t.backtraceGraph, sourceDir, ii.backtrace, 300));
|
||||||
}
|
}
|
||||||
|
for (const DefineInfo &di : ci.defines) {
|
||||||
|
ct.defineDefinitions.append(
|
||||||
|
extractBacktraceInformation(t.backtraceGraph, sourceDir, di.backtrace, 400));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const InstallDestination &id : t.installDestination) {
|
||||||
|
ct.includeDefinitions.append(
|
||||||
|
extractBacktraceInformation(t.backtraceGraph, sourceDir, id.backtrace, 500));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ct;
|
return ct;
|
||||||
@@ -309,64 +356,6 @@ void addProjects(const QHash<Utils::FilePath, ProjectNode *> &cmakeListsNodes,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addBacktraceInformation(FolderNode *node,
|
|
||||||
const BacktraceInfo &backtraces,
|
|
||||||
const QDir &sourceDir,
|
|
||||||
int backtraceIndex)
|
|
||||||
{
|
|
||||||
QVector<FolderNode::LocationInfo> info;
|
|
||||||
// Set up a default target path:
|
|
||||||
FilePath targetPath = node->filePath().pathAppended("CMakeLists.txt");
|
|
||||||
while (backtraceIndex != -1) {
|
|
||||||
const size_t bi = static_cast<size_t>(backtraceIndex);
|
|
||||||
QTC_ASSERT(bi < backtraces.nodes.size(), break);
|
|
||||||
const BacktraceNode &btNode = backtraces.nodes[bi];
|
|
||||||
backtraceIndex = btNode.parent; // advance to next node
|
|
||||||
|
|
||||||
const size_t fileIndex = static_cast<size_t>(btNode.file);
|
|
||||||
QTC_ASSERT(fileIndex < backtraces.files.size(), break);
|
|
||||||
const FilePath path = FilePath::fromString(
|
|
||||||
sourceDir.absoluteFilePath(backtraces.files[fileIndex]));
|
|
||||||
|
|
||||||
if (btNode.command < 0) {
|
|
||||||
// No command, skip: The file itself is already covered:-)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t commandIndex = static_cast<size_t>(btNode.command);
|
|
||||||
QTC_ASSERT(commandIndex < backtraces.commands.size(), break);
|
|
||||||
|
|
||||||
const QString command = backtraces.commands[commandIndex];
|
|
||||||
|
|
||||||
QString dn;
|
|
||||||
if (path == targetPath) {
|
|
||||||
if (btNode.line > 0) {
|
|
||||||
dn = QCoreApplication::translate("CMakeProjectManager::Internal::FileApiReader",
|
|
||||||
"%1 in line %2")
|
|
||||||
.arg(command)
|
|
||||||
.arg(btNode.line);
|
|
||||||
} else {
|
|
||||||
dn = command;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (btNode.line > 0) {
|
|
||||||
dn = QCoreApplication::translate("CMakeProjectManager::Internal::FileApiReader",
|
|
||||||
"%1 in %2:%3")
|
|
||||||
.arg(command)
|
|
||||||
.arg(path.toUserOutput())
|
|
||||||
.arg(btNode.line);
|
|
||||||
} else {
|
|
||||||
dn = QCoreApplication::translate("CMakeProjectManager::Internal::FileApiReader",
|
|
||||||
"%1 in %2")
|
|
||||||
.arg(command)
|
|
||||||
.arg(path.toUserOutput());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
info.append(FolderNode::LocationInfo(dn, path, btNode.line));
|
|
||||||
}
|
|
||||||
node->setLocationInfo(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
QVector<FolderNode *> addSourceGroups(ProjectNode *targetRoot,
|
QVector<FolderNode *> addSourceGroups(ProjectNode *targetRoot,
|
||||||
const TargetDetails &td,
|
const TargetDetails &td,
|
||||||
const FilePath &sourceDirectory)
|
const FilePath &sourceDirectory)
|
||||||
@@ -479,8 +468,6 @@ void addTargets(const QHash<Utils::FilePath, ProjectExplorer::ProjectNode *> &cm
|
|||||||
tNode->setTargetInformation(td.artifacts, td.type);
|
tNode->setTargetInformation(td.artifacts, td.type);
|
||||||
tNode->setBuildDirectory(directoryBuildDir(config, buildDir, t.directory));
|
tNode->setBuildDirectory(directoryBuildDir(config, buildDir, t.directory));
|
||||||
|
|
||||||
addBacktraceInformation(tNode, td.backtraceGraph, sourceDir, td.backtrace);
|
|
||||||
|
|
||||||
addCompileGroups(tNode, topSourceDir, dir, tNode->buildDirectory(), td, knownHeaderNodes);
|
addCompileGroups(tNode, topSourceDir, dir, tNode->buildDirectory(), td, knownHeaderNodes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -534,6 +521,44 @@ std::pair<std::unique_ptr<CMakeProjectNode>, QSet<FilePath>> generateRootProject
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setupLocationInfoForTargets(CMakeProjectNode *rootNode, const QList<CMakeBuildTarget> &targets)
|
||||||
|
{
|
||||||
|
for (const CMakeBuildTarget &t : targets) {
|
||||||
|
FolderNode *folderNode = static_cast<FolderNode *>(
|
||||||
|
rootNode->findNode(Utils::equal(&Node::buildKey, t.title)));
|
||||||
|
if (folderNode) {
|
||||||
|
QSet<std::pair<FilePath, int>> locations;
|
||||||
|
auto dedup = [&locations](const Backtrace &bt) {
|
||||||
|
QVector<FolderNode::LocationInfo> result;
|
||||||
|
for (const FolderNode::LocationInfo &i : bt) {
|
||||||
|
int count = locations.count();
|
||||||
|
locations.insert(std::make_pair(i.path, i.line));
|
||||||
|
if (count != locations.count()) {
|
||||||
|
result.append(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
QVector<FolderNode::LocationInfo> result = dedup(t.backtrace);
|
||||||
|
auto dedupMulti = [&dedup](const Backtraces &bts) {
|
||||||
|
QVector<FolderNode::LocationInfo> result;
|
||||||
|
for (const Backtrace &bt : bts) {
|
||||||
|
result.append(dedup(bt));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
result += dedupMulti(t.dependencyDefinitions);
|
||||||
|
result += dedupMulti(t.includeDefinitions);
|
||||||
|
result += dedupMulti(t.defineDefinitions);
|
||||||
|
result += dedupMulti(t.sourceDefinitions);
|
||||||
|
result += dedupMulti(t.installDefinitions);
|
||||||
|
|
||||||
|
folderNode->setLocationInfo(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace CMakeProjectManager {
|
namespace CMakeProjectManager {
|
||||||
@@ -566,6 +591,8 @@ FileApiQtcData extractData(FileApiData &input,
|
|||||||
result.rootProjectNode = std::move(pair.first);
|
result.rootProjectNode = std::move(pair.first);
|
||||||
result.knownHeaders = std::move(pair.second);
|
result.knownHeaders = std::move(pair.second);
|
||||||
|
|
||||||
|
setupLocationInfoForTargets(result.rootProjectNode.get(), result.buildTargets);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user