Clang: implement current document filter

Filter is based on full token infos which come
from clang code model after token infos with pure
highlighting information.

Inprovements:
- functions also provide the return type after the signature
- now supports Q_PROPERTY
- all c++ features that clang 5.0 supports

Change-Id: If3e30d238984f39df8d2c3b9ba3ee085c4117f3d
Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
Ivan Donchevskii
2017-11-27 15:51:18 +01:00
parent c39f28d5e0
commit 432ae65944
4 changed files with 150 additions and 4 deletions

View File

@@ -27,6 +27,8 @@
#include "optional.h" #include "optional.h"
#include <QMetaType>
namespace Utils { namespace Utils {
class LineColumn class LineColumn
@@ -57,3 +59,5 @@ public:
using OptionalLineColumn = optional<LineColumn>; using OptionalLineColumn = optional<LineColumn>;
} // namespace Utils } // namespace Utils
Q_DECLARE_METATYPE(Utils::LineColumn)

View File

@@ -25,8 +25,28 @@
#include "clangcurrentdocumentfilter.h" #include "clangcurrentdocumentfilter.h"
#include "clangeditordocumentprocessor.h"
#include "clangutils.h"
#include <clangsupport/tokeninfocontainer.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <cplusplus/Icons.h>
#include <cpptools/cpptoolsconstants.h> #include <cpptools/cpptoolsconstants.h>
#include <texteditor/textdocument.h>
#include <utils/algorithm.h>
#include <utils/fuzzymatcher.h>
#include <utils/linecolumn.h>
#include <utils/textutils.h>
#include <utils/qtcassert.h>
#include <QRegularExpression>
namespace ClangCodeModel { namespace ClangCodeModel {
ClangCurrentDocumentFilter::ClangCurrentDocumentFilter() ClangCurrentDocumentFilter::ClangCurrentDocumentFilter()
@@ -36,22 +56,131 @@ ClangCurrentDocumentFilter::ClangCurrentDocumentFilter()
setShortcutString(QString(QLatin1Char('.'))); setShortcutString(QString(QLatin1Char('.')));
setPriority(High); setPriority(High);
setIncludedByDefault(false); setIncludedByDefault(false);
Core::EditorManager *editorManager = Core::EditorManager::instance();
connect(editorManager, &Core::EditorManager::currentEditorChanged,
this, &ClangCurrentDocumentFilter::onCurrentEditorChanged,
Qt::QueuedConnection);
connect(editorManager, &Core::EditorManager::editorAboutToClose,
this, &ClangCurrentDocumentFilter::onEditorAboutToClose,
Qt::QueuedConnection);
}
static QString addResultTypeToFunctionSignature(const QString &signature,
const ClangBackEnd::ExtraInfo &extraInfo)
{
return signature + extraInfo.typeSpelling.toString() + QLatin1String(" -> ", 4)
+ extraInfo.resultTypeSpelling.toString();
}
static QString addTypeToVariableName(const QString &name, const ClangBackEnd::ExtraInfo &extraInfo)
{
return extraInfo.typeSpelling.toString() + QLatin1String(" ") + name;
}
static Core::LocatorFilterEntry makeEntry(Core::ILocatorFilter *filter,
const ClangBackEnd::TokenInfoContainer &info)
{
const ClangBackEnd::ExtraInfo &extraInfo = info.extraInfo();
QString displayName = extraInfo.token;
::Utils::LineColumn lineColumn(static_cast<int>(info.line()),
static_cast<int>(info.column()));
Core::LocatorFilterEntry entry(filter, displayName, qVariantFromValue(lineColumn));
QString extra;
ClangBackEnd::HighlightingType mainType = info.types().mainHighlightingType;
if (mainType == ClangBackEnd::HighlightingType::VirtualFunction
|| mainType == ClangBackEnd::HighlightingType::Function) {
displayName = addResultTypeToFunctionSignature(displayName, extraInfo);
extra = extraInfo.semanticParentTypeSpelling.toString();
} else if (mainType == ClangBackEnd::HighlightingType::GlobalVariable
|| mainType == ClangBackEnd::HighlightingType::Field
|| mainType == ClangBackEnd::HighlightingType::QtProperty) {
displayName = addTypeToVariableName(displayName, extraInfo);
extra = extraInfo.semanticParentTypeSpelling.toString();
} else {
extra = extraInfo.typeSpelling.toString();
}
entry.displayName = displayName;
entry.extraInfo = extra;
entry.displayIcon = CPlusPlus::Icons::iconForType(Utils::iconTypeForToken(info));
return entry;
} }
QList<Core::LocatorFilterEntry> ClangCurrentDocumentFilter::matchesFor( QList<Core::LocatorFilterEntry> ClangCurrentDocumentFilter::matchesFor(
QFutureInterface<Core::LocatorFilterEntry> &, const QString &) QFutureInterface<Core::LocatorFilterEntry> &, const QString &entry)
{ {
return QList<Core::LocatorFilterEntry>(); QList<Core::LocatorFilterEntry> goodEntries;
if (!m_currentEditor)
return goodEntries;
FuzzyMatcher::CaseSensitivity caseSesitivity = caseSensitivity(entry) == Qt::CaseSensitive
? FuzzyMatcher::CaseSensitivity::CaseSensitive
: FuzzyMatcher::CaseSensitivity::CaseInsensitive;
const QRegularExpression regexp = FuzzyMatcher::createRegExp(entry, caseSesitivity);
if (!regexp.isValid())
return goodEntries;
using Internal::ClangEditorDocumentProcessor;
ClangEditorDocumentProcessor *processor = ClangEditorDocumentProcessor::get(m_currentPath);
if (!processor)
return goodEntries;
using TokInfoContainer = ClangBackEnd::TokenInfoContainer;
const QVector<TokInfoContainer> &infos = processor->tokenInfos();
for (const TokInfoContainer &info : infos) {
if (!info.extraInfo().declaration)
continue;
if (info.types().mainHighlightingType == ClangBackEnd::HighlightingType::LocalVariable)
continue;
QRegularExpressionMatch match = regexp.match(info.extraInfo().token);
if (match.hasMatch())
goodEntries.push_back(makeEntry(this, info));
}
return goodEntries;
} }
void ClangCurrentDocumentFilter::accept(Core::LocatorFilterEntry, QString *, int *, int *) const void ClangCurrentDocumentFilter::accept(Core::LocatorFilterEntry selection,
QString *, int *, int *) const
{ {
if (!m_currentEditor)
return;
auto lineColumn = qvariant_cast<::Utils::LineColumn>(selection.internalData);
Core::EditorManager::openEditorAt(m_currentPath, lineColumn.line,
lineColumn.column - 1);
} }
void ClangCurrentDocumentFilter::refresh(QFutureInterface<void> &) void ClangCurrentDocumentFilter::refresh(QFutureInterface<void> &)
{ {
}
void ClangCurrentDocumentFilter::reset()
{
m_currentEditor = nullptr;
m_currentPath.clear();
}
void ClangCurrentDocumentFilter::onEditorAboutToClose(Core::IEditor *editorAboutToClose)
{
if (!editorAboutToClose)
return;
if (m_currentEditor == editorAboutToClose)
reset();
}
void ClangCurrentDocumentFilter::onCurrentEditorChanged(Core::IEditor *newCurrent)
{
if (newCurrent) {
m_currentEditor = newCurrent;
Core::IDocument *document = m_currentEditor->document();
QTC_ASSERT(document, return;);
auto *textDocument = qobject_cast<TextEditor::TextDocument *>(document);
m_currentPath = textDocument->filePath().toString();
} else {
reset();
}
} }
} // namespace ClangCodeModel } // namespace ClangCodeModel

View File

@@ -27,6 +27,8 @@
#include <coreplugin/locator/ilocatorfilter.h> #include <coreplugin/locator/ilocatorfilter.h>
namespace Core { class IEditor; }
namespace ClangCodeModel { namespace ClangCodeModel {
class ClangCurrentDocumentFilter : public Core::ILocatorFilter class ClangCurrentDocumentFilter : public Core::ILocatorFilter
@@ -41,6 +43,14 @@ public:
void accept(Core::LocatorFilterEntry selection, void accept(Core::LocatorFilterEntry selection,
QString *newText, int *selectionStart, int *selectionLength) const override; QString *newText, int *selectionStart, int *selectionLength) const override;
void refresh(QFutureInterface<void> &future) override; void refresh(QFutureInterface<void> &future) override;
private:
void onEditorAboutToClose(Core::IEditor *editors);
void onCurrentEditorChanged(Core::IEditor *newCurrent);
void reset();
Core::IEditor *m_currentEditor = nullptr;
QString m_currentPath;
}; };
} // namespace ClangCodeModel } // namespace ClangCodeModel

View File

@@ -89,6 +89,9 @@ ModelManagerSupportClang::ModelManagerSupportClang()
else else
m_followSymbol.reset(new CppTools::FollowSymbolUnderCursor); m_followSymbol.reset(new CppTools::FollowSymbolUnderCursor);
CppTools::CppModelManager::instance()->setCurrentDocumentFilter(
std::make_unique<ClangCurrentDocumentFilter>());
Core::EditorManager *editorManager = Core::EditorManager::instance(); Core::EditorManager *editorManager = Core::EditorManager::instance();
connect(editorManager, &Core::EditorManager::editorOpened, connect(editorManager, &Core::EditorManager::editorOpened,
this, &ModelManagerSupportClang::onEditorOpened); this, &ModelManagerSupportClang::onEditorOpened);