Files
qt-creator/src/plugins/clangcodemodel/clangcompleter.cpp

214 lines
5.9 KiB
C++
Raw Normal View History

/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://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 http://www.qt.io/terms-conditions. For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "clangcompleter.h"
#include "sourcemarker.h"
#include "unsavedfiledata.h"
#include "utils_p.h"
#include "completionproposalsbuilder.h"
#include "raii/scopedclangoptions.h"
#include "unit.h"
#include <QDebug>
#include <QFile>
#include <QMutex>
#include <QMutexLocker>
#include <QTime>
#include <clang-c/Index.h>
//#define TIME_COMPLETION
using namespace ClangCodeModel::Internal;
namespace ClangCodeModel {
class ClangCompleter::PrivateData
{
public:
PrivateData()
: m_mutex(QMutex::Recursive)
, m_unit(Unit::create())
, m_isSignalSlotCompletion(false)
{
}
~PrivateData()
{
}
bool parseFromFile(const UnsavedFiles &unsavedFiles)
{
Q_ASSERT(!m_unit->isLoaded());
if (m_unit->fileName().isEmpty())
return false;
unsigned opts = clang_defaultEditingTranslationUnitOptions();
#if defined(CINDEX_VERSION) && (CINDEX_VERSION > 5)
opts |= CXTranslationUnit_CacheCompletionResults;
opts |= CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;
#endif
m_unit->setManagementOptions(opts);
m_unit->setUnsavedFiles(unsavedFiles);
m_unit->parse();
return m_unit->isLoaded();
}
public:
QMutex m_mutex;
Unit::Ptr m_unit;
bool m_isSignalSlotCompletion;
};
/**
* @brief Constructs with highest possible priority
*/
CodeCompletionResult::CodeCompletionResult()
: m_priority(SHRT_MAX)
, m_completionKind(Other)
, m_availability(Available)
, m_hasParameters(false)
{}
/**
* @brief Constructs with given priority
* @param priority Will be reversed, because clang's highest priority is 0,
* but inside QtCreator it is the lowest priority
*/
CodeCompletionResult::CodeCompletionResult(unsigned priority)
: m_priority(SHRT_MAX - priority)
, m_completionKind(Other)
, m_availability(Available)
, m_hasParameters(false)
{
}
ClangCompleter::ClangCompleter()
: d(new PrivateData)
{
}
ClangCompleter::~ClangCompleter()
{
}
QString ClangCompleter::fileName() const
{
return d->m_unit->fileName();
}
void ClangCompleter::setFileName(const QString &fileName)
{
if (d->m_unit->fileName() != fileName) {
d->m_unit = Unit::create(fileName);
}
}
QStringList ClangCompleter::options() const
{
return d->m_unit->compilationOptions();
}
void ClangCompleter::setOptions(const QStringList &options) const
{
if (d->m_unit->compilationOptions() != options) {
d->m_unit->setCompilationOptions(options);
d->m_unit->unload();
}
}
bool ClangCompleter::isSignalSlotCompletion() const
{
return d->m_isSignalSlotCompletion;
}
void ClangCompleter::setSignalSlotCompletion(bool isSignalSlot)
{
d->m_isSignalSlotCompletion = isSignalSlot;
}
bool ClangCompleter::reparse(const UnsavedFiles &unsavedFiles)
{
if (!d->m_unit->isLoaded())
return d->parseFromFile(unsavedFiles);
d->m_unit->setUnsavedFiles(unsavedFiles);
d->m_unit->reparse();
return d->m_unit->isLoaded();
}
QList<CodeCompletionResult> ClangCompleter::codeCompleteAt(unsigned line,
unsigned column,
const UnsavedFiles &unsavedFiles)
{
#ifdef TIME_COMPLETION
QTime t;t.start();
#endif // TIME_COMPLETION
if (!d->m_unit->isLoaded())
if (!d->parseFromFile(unsavedFiles))
return QList<CodeCompletionResult>();
ScopedCXCodeCompleteResults results;
d->m_unit->setUnsavedFiles(unsavedFiles);
d->m_unit->codeCompleteAt(line, column, results);
QList<CodeCompletionResult> completions;
if (results) {
const quint64 contexts = clang_codeCompleteGetContexts(results);
CompletionProposalsBuilder builder(completions, contexts, d->m_isSignalSlotCompletion);
for (unsigned i = 0; i < results.size(); ++i)
builder(results.completionAt(i));
}
#ifdef TIME_COMPLETION
qDebug() << "Completion timing:" << completions.size() << "results in" << t.elapsed() << "ms.";
#endif // TIME_COMPLETION
return completions;
}
bool ClangCompleter::objcEnabled() const
{
static const QString objcppOption = QLatin1String("-ObjC++");
static const QString objcOption = QLatin1String("-ObjC");
QStringList options = d->m_unit->compilationOptions();
return options.contains(objcOption) || options.contains(objcppOption);
}
QMutex *ClangCompleter::mutex() const
{
return &d->m_mutex;
}
} // namespace ClangCodeModel