CompilationDatabase: Ask for the root path and scan for headers

Let's use the same approach we have for CMake projects by using
the same TreeScanner class.

Compilation database does not have a concept of the root directory
so let's show a file dialog and ask for it the first time the project
is loaded. Next times we open it we take this path from settings.
This root path can later be changed from the project tree context menu.

Fixes: QTCREATORBUG-22031
Change-Id: I151aed8d0504b2e8aa14aa774cad25f8c86d5c17
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Ivan Donchevskii
2019-03-14 15:34:14 +01:00
committed by hjk
parent d34eb692fe
commit 2c5808bada
16 changed files with 197 additions and 47 deletions

View File

@@ -30,11 +30,11 @@
#include "builddirmanager.h"
#include "cmakebuildtarget.h"
#include "cmakeprojectimporter.h"
#include "treescanner.h"
#include <projectexplorer/extracompiler.h>
#include <projectexplorer/projectmacro.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectmacro.h>
#include <projectexplorer/treescanner.h>
#include <utils/fileutils.h>
@@ -108,7 +108,7 @@ private:
CppTools::CppProjectUpdater *m_cppCodeModelUpdater = nullptr;
QList<ProjectExplorer::ExtraCompiler *> m_extraCompilers;
Internal::TreeScanner m_treeScanner;
ProjectExplorer::TreeScanner m_treeScanner;
Internal::BuildDirManager m_buildDirManager;
bool m_waitingForScan = false;

View File

@@ -35,8 +35,7 @@ HEADERS = builddirmanager.h \
configmodelitemdelegate.h \
servermode.h \
servermodereader.h \
tealeafreader.h \
treescanner.h
tealeafreader.h
SOURCES = builddirmanager.cpp \
builddirparameters.cpp \
@@ -70,8 +69,7 @@ SOURCES = builddirmanager.cpp \
configmodelitemdelegate.cpp \
servermode.cpp \
servermodereader.cpp \
tealeafreader.cpp \
treescanner.cpp \
tealeafreader.cpp
RESOURCES += cmakeproject.qrc

View File

@@ -88,8 +88,6 @@ QtcPlugin {
"servermodereader.cpp",
"servermodereader.h",
"tealeafreader.cpp",
"tealeafreader.h",
"treescanner.cpp",
"treescanner.h",
"tealeafreader.h"
]
}

View File

@@ -1,180 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 Alexander Drozdov.
** Contact: Alexander Drozdov (adrozdoff@gmail.com)
**
** 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 "treescanner.h"
#include <coreplugin/iversioncontrol.h>
#include <coreplugin/vcsmanager.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <cpptools/cpptoolsconstants.h>
#include <utils/qtcassert.h>
#include <utils/algorithm.h>
#include <utils/runextensions.h>
#include <memory>
using namespace ProjectExplorer;
namespace CMakeProjectManager {
namespace Internal {
TreeScanner::TreeScanner(QObject *parent) : QObject(parent)
{
m_factory = TreeScanner::genericFileType;
m_filter = [](const Utils::MimeType &mimeType, const Utils::FileName &fn) {
return isWellKnownBinary(mimeType, fn) && isMimeBinary(mimeType, fn);
};
connect(&m_futureWatcher, &FutureWatcher::finished, this, &TreeScanner::finished);
}
TreeScanner::~TreeScanner()
{
if (!m_futureWatcher.isFinished()) {
m_futureWatcher.cancel();
m_futureWatcher.waitForFinished();
}
}
bool TreeScanner::asyncScanForFiles(const Utils::FileName &directory)
{
if (!m_futureWatcher.isFinished())
return false;
auto fi = new FutureInterface();
m_scanFuture = fi->future();
m_futureWatcher.setFuture(m_scanFuture);
Utils::runAsync([this, fi, directory]() { TreeScanner::scanForFiles(fi, directory, m_filter, m_factory); });
return true;
}
void TreeScanner::setFilter(TreeScanner::FileFilter filter)
{
if (isFinished())
m_filter = filter;
}
void TreeScanner::setTypeFactory(TreeScanner::FileTypeFactory factory)
{
if (isFinished())
m_factory = factory;
}
TreeScanner::Future TreeScanner::future() const
{
return m_scanFuture;
}
bool TreeScanner::isFinished() const
{
return m_futureWatcher.isFinished();
}
TreeScanner::Result TreeScanner::result() const
{
if (isFinished())
return m_scanFuture.result();
return Result();
}
TreeScanner::Result TreeScanner::release()
{
if (isFinished()) {
auto result = m_scanFuture.result();
m_scanFuture = Future();
return result;
}
return Result();
}
void TreeScanner::reset()
{
if (isFinished())
m_scanFuture = Future();
}
bool TreeScanner::isWellKnownBinary(const Utils::MimeType & /*mdb*/, const Utils::FileName &fn)
{
return fn.endsWith(QLatin1String(".a")) ||
fn.endsWith(QLatin1String(".o")) ||
fn.endsWith(QLatin1String(".d")) ||
fn.endsWith(QLatin1String(".exe")) ||
fn.endsWith(QLatin1String(".dll")) ||
fn.endsWith(QLatin1String(".obj")) ||
fn.endsWith(QLatin1String(".elf"));
}
bool TreeScanner::isMimeBinary(const Utils::MimeType &mimeType, const Utils::FileName &/*fn*/)
{
bool isBinary = false;
if (mimeType.isValid()) {
QStringList mimes;
mimes << mimeType.name() << mimeType.allAncestors();
isBinary = !mimes.contains(QLatin1String("text/plain"));
}
return isBinary;
}
FileType TreeScanner::genericFileType(const Utils::MimeType &mimeType, const Utils::FileName &/*fn*/)
{
return Node::fileTypeForMimeType(mimeType);
}
void TreeScanner::scanForFiles(FutureInterface *fi, const Utils::FileName& directory,
const FileFilter &filter, const FileTypeFactory &factory)
{
std::unique_ptr<FutureInterface> fip(fi);
fip->reportStarted();
Result nodes = FileNode::scanForFiles(
directory,
[&filter, &factory](const Utils::FileName &fn) -> FileNode * {
const Utils::MimeType mimeType = Utils::mimeTypeForFile(fn.toString());
// Skip some files during scan.
if (filter && filter(mimeType, fn))
return nullptr;
// Type detection
FileType type = FileType::Unknown;
if (factory)
type = factory(mimeType, fn);
return new FileNode(fn, type);
}, fip.get());
Utils::sort(nodes, ProjectExplorer::Node::sortByPath);
fip->setProgressValue(fip->progressMaximum());
fip->reportResult(nodes);
fip->reportFinished();
}
} // namespace Internal
} // namespace CMakeProjectManager

View File

@@ -1,104 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 Alexander Drozdov.
** Contact: Alexander Drozdov (adrozdoff@gmail.com)
**
** 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/projectnodes.h"
#include <utils/mimetypes/mimedatabase.h>
#include <utils/fileutils.h>
#include <QObject>
#include <QFuture>
#include <QFutureWatcher>
#include <functional>
namespace Core { class IVersionControl; }
namespace CMakeProjectManager {
namespace Internal {
class TreeScanner : public QObject
{
Q_OBJECT
public:
using Result = QList<ProjectExplorer::FileNode *>;
using Future = QFuture<Result>;
using FutureWatcher = QFutureWatcher<Result>;
using FutureInterface = QFutureInterface<Result>;
using FileFilter = std::function<bool(const Utils::MimeType &, const Utils::FileName &)>;
using FileTypeFactory = std::function<ProjectExplorer::FileType(const Utils::MimeType &, const Utils::FileName &)>;
explicit TreeScanner(QObject *parent = nullptr);
~TreeScanner() override;
// Start scanning in given directory
bool asyncScanForFiles(const Utils::FileName& directory);
// Setup filter for ignored files
void setFilter(FileFilter filter);
// Setup factory for file types
void setTypeFactory(FileTypeFactory factory);
Future future() const;
bool isFinished() const;
// Takes not-owning result
Result result() const;
// Takes owning of result
Result release();
// Clear scan results
void reset();
// Standard filters helpers
static bool isWellKnownBinary(const Utils::MimeType &mimeType, const Utils::FileName &fn);
static bool isMimeBinary(const Utils::MimeType &mimeType, const Utils::FileName &fn);
// Standard file factory
static ProjectExplorer::FileType genericFileType(const Utils::MimeType &mdb, const Utils::FileName& fn);
signals:
void finished();
private:
static void scanForFiles(FutureInterface *fi, const Utils::FileName &directory,
const FileFilter &filter, const FileTypeFactory &factory);
private:
FileFilter m_filter;
FileTypeFactory m_factory;
FutureWatcher m_futureWatcher;
Future m_scanFuture;
};
} // namespace Internal
} // namespace CMakeProjectManager