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
|
||||
for (CMakeBuildTarget &t : readerTargets) {
|
||||
if (t.definitionFile.isEmpty()) {
|
||||
t.definitionFile = t.sourceDirectory.pathAppended("CMakeLists.txt");
|
||||
if (t.backtrace.isEmpty()) {
|
||||
t.backtrace.append(
|
||||
FolderNode::LocationInfo(tr("CMakeLists.txt in source directory"),
|
||||
t.sourceDirectory.pathAppended("CMakeLists.txt")));
|
||||
}
|
||||
}
|
||||
result.append(readerTargets);
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include "cmake_global.h"
|
||||
|
||||
#include <projectexplorer/projectmacro.h>
|
||||
#include <projectexplorer/projectnodes.h>
|
||||
|
||||
#include <utils/fileutils.h>
|
||||
|
||||
@@ -43,6 +44,9 @@ enum TargetType {
|
||||
UtilityType
|
||||
};
|
||||
|
||||
using Backtrace = QVector<ProjectExplorer::FolderNode::LocationInfo>;
|
||||
using Backtraces = QVector<Backtrace>;
|
||||
|
||||
class CMAKE_EXPORT CMakeBuildTarget
|
||||
{
|
||||
public:
|
||||
@@ -53,8 +57,13 @@ public:
|
||||
Utils::FilePath sourceDirectory;
|
||||
Utils::FilePath makeCommand;
|
||||
|
||||
Utils::FilePath definitionFile;
|
||||
int definitionLine = -1;
|
||||
Backtrace backtrace;
|
||||
|
||||
Backtraces dependencyDefinitions;
|
||||
Backtraces sourceDefinitions;
|
||||
Backtraces defineDefinitions;
|
||||
Backtraces includeDefinitions;
|
||||
Backtraces installDefinitions;
|
||||
|
||||
// code model
|
||||
QList<Utils::FilePath> includeFiles;
|
||||
|
@@ -75,12 +75,13 @@ void CMakeTargetLocatorFilter::prepareSearch(const QString &entry)
|
||||
for (const CMakeBuildTarget &target : buildTargets) {
|
||||
const int index = target.title.indexOf(entry);
|
||||
if (index >= 0) {
|
||||
const FilePath path = target.definitionFile.isEmpty()
|
||||
? cmakeProject->projectFilePath()
|
||||
: target.definitionFile;
|
||||
const FilePath path = target.backtrace.isEmpty() ? cmakeProject->projectFilePath()
|
||||
: target.backtrace.first().path;
|
||||
const int line = target.backtrace.isEmpty() ? -1 : target.backtrace.first().line;
|
||||
|
||||
QVariantMap extraData;
|
||||
extraData.insert("project", cmakeProject->projectFilePath().toString());
|
||||
extraData.insert("line", target.definitionLine);
|
||||
extraData.insert("line", line);
|
||||
extraData.insert("file", path.toString());
|
||||
|
||||
Core::LocatorFilterEntry filterEntry(this, target.title, extraData);
|
||||
|
@@ -165,6 +165,39 @@ PreprocessedData preprocess(FileApiData &data,
|
||||
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,
|
||||
const FilePath &sourceDirectory,
|
||||
const FilePath &buildDirectory)
|
||||
@@ -198,15 +231,29 @@ QList<CMakeBuildTarget> generateBuildTargets(const PreprocessedData &input,
|
||||
ct.sourceDirectory = FilePath::fromString(
|
||||
QDir::cleanPath(sourceDir.absoluteFilePath(t.sourceDir.toString())));
|
||||
|
||||
if (t.backtrace >= 0) {
|
||||
const BacktraceNode &node = t.backtraceGraph.nodes[static_cast<size_t>(t.backtrace)];
|
||||
const int fileIndex = node.file;
|
||||
if (fileIndex >= 0) {
|
||||
ct.definitionFile = FilePath::fromString(
|
||||
QDir::cleanPath(sourceDir.absoluteFilePath(
|
||||
t.backtraceGraph.files[static_cast<size_t>(fileIndex)])));
|
||||
ct.definitionLine = node.line;
|
||||
ct.backtrace = extractBacktraceInformation(t.backtraceGraph, sourceDir, t.backtrace, 0);
|
||||
|
||||
for (const DependencyInfo &d : t.dependencies) {
|
||||
ct.dependencyDefinitions.append(
|
||||
extractBacktraceInformation(t.backtraceGraph, sourceDir, d.backtrace, 100));
|
||||
}
|
||||
for (const SourceInfo &si : t.sources) {
|
||||
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;
|
||||
@@ -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,
|
||||
const TargetDetails &td,
|
||||
const FilePath &sourceDirectory)
|
||||
@@ -479,8 +468,6 @@ void addTargets(const QHash<Utils::FilePath, ProjectExplorer::ProjectNode *> &cm
|
||||
tNode->setTargetInformation(td.artifacts, td.type);
|
||||
tNode->setBuildDirectory(directoryBuildDir(config, buildDir, t.directory));
|
||||
|
||||
addBacktraceInformation(tNode, td.backtraceGraph, sourceDir, td.backtrace);
|
||||
|
||||
addCompileGroups(tNode, topSourceDir, dir, tNode->buildDirectory(), td, knownHeaderNodes);
|
||||
}
|
||||
}
|
||||
@@ -534,6 +521,44 @@ std::pair<std::unique_ptr<CMakeProjectNode>, QSet<FilePath>> generateRootProject
|
||||
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 CMakeProjectManager {
|
||||
@@ -566,6 +591,8 @@ FileApiQtcData extractData(FileApiData &input,
|
||||
result.rootProjectNode = std::move(pair.first);
|
||||
result.knownHeaders = std::move(pair.second);
|
||||
|
||||
setupLocationInfoForTargets(result.rootProjectNode.get(), result.buildTargets);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user