From 432ae65944701980a8fc792d25d792e40968db08 Mon Sep 17 00:00:00 2001 From: Ivan Donchevskii Date: Mon, 27 Nov 2017 15:51:18 +0100 Subject: [PATCH] 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 --- src/libs/utils/linecolumn.h | 4 + .../clangcurrentdocumentfilter.cpp | 137 +++++++++++++++++- .../clangcurrentdocumentfilter.h | 10 ++ .../clangmodelmanagersupport.cpp | 3 + 4 files changed, 150 insertions(+), 4 deletions(-) diff --git a/src/libs/utils/linecolumn.h b/src/libs/utils/linecolumn.h index b31fe40ba52..003ba3ef342 100644 --- a/src/libs/utils/linecolumn.h +++ b/src/libs/utils/linecolumn.h @@ -27,6 +27,8 @@ #include "optional.h" +#include + namespace Utils { class LineColumn @@ -57,3 +59,5 @@ public: using OptionalLineColumn = optional; } // namespace Utils + +Q_DECLARE_METATYPE(Utils::LineColumn) diff --git a/src/plugins/clangcodemodel/clangcurrentdocumentfilter.cpp b/src/plugins/clangcodemodel/clangcurrentdocumentfilter.cpp index b28ac972918..d5a84b611d4 100644 --- a/src/plugins/clangcodemodel/clangcurrentdocumentfilter.cpp +++ b/src/plugins/clangcodemodel/clangcurrentdocumentfilter.cpp @@ -25,8 +25,28 @@ #include "clangcurrentdocumentfilter.h" +#include "clangeditordocumentprocessor.h" +#include "clangutils.h" + +#include + +#include +#include + +#include + #include +#include + +#include +#include +#include +#include +#include + +#include + namespace ClangCodeModel { ClangCurrentDocumentFilter::ClangCurrentDocumentFilter() @@ -36,22 +56,131 @@ ClangCurrentDocumentFilter::ClangCurrentDocumentFilter() setShortcutString(QString(QLatin1Char('.'))); setPriority(High); 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(info.line()), + static_cast(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 ClangCurrentDocumentFilter::matchesFor( - QFutureInterface &, const QString &) + QFutureInterface &, const QString &entry) { - return QList(); + QList 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 &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 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(document); + m_currentPath = textDocument->filePath().toString(); + } else { + reset(); + } } } // namespace ClangCodeModel diff --git a/src/plugins/clangcodemodel/clangcurrentdocumentfilter.h b/src/plugins/clangcodemodel/clangcurrentdocumentfilter.h index 6adba5d775e..e355862bdf2 100644 --- a/src/plugins/clangcodemodel/clangcurrentdocumentfilter.h +++ b/src/plugins/clangcodemodel/clangcurrentdocumentfilter.h @@ -27,6 +27,8 @@ #include +namespace Core { class IEditor; } + namespace ClangCodeModel { class ClangCurrentDocumentFilter : public Core::ILocatorFilter @@ -41,6 +43,14 @@ public: void accept(Core::LocatorFilterEntry selection, QString *newText, int *selectionStart, int *selectionLength) const override; void refresh(QFutureInterface &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 diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index 4859504e29f..8ce75e5fdc1 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -89,6 +89,9 @@ ModelManagerSupportClang::ModelManagerSupportClang() else m_followSymbol.reset(new CppTools::FollowSymbolUnderCursor); + CppTools::CppModelManager::instance()->setCurrentDocumentFilter( + std::make_unique()); + Core::EditorManager *editorManager = Core::EditorManager::instance(); connect(editorManager, &Core::EditorManager::editorOpened, this, &ModelManagerSupportClang::onEditorOpened);