diff --git a/kdevplatform/language/codecompletion/codecompletiontesthelper.h b/kdevplatform/language/codecompletion/codecompletiontesthelper.h index b5ac341d9c..02a191a938 100644 --- a/kdevplatform/language/codecompletion/codecompletiontesthelper.h +++ b/kdevplatform/language/codecompletion/codecompletiontesthelper.h @@ -1,236 +1,236 @@ /* This file is part of KDevelop Copyright 2006 Hamish Rodda Copyright 2007-2009 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_CODECOMPLETIONTESTHELPER_H #define KDEVPLATFORM_CODECOMPLETIONTESTHELPER_H #include #include #include "../duchain/declaration.h" #include "../duchain/duchain.h" #include "codecompletionitem.h" #include #include #include #include using namespace KTextEditor; using namespace KDevelop; /** * Helper-class for testing completion-items * Just initialize it with the context and the text, and then use the members, for simple cases only "names" * the template parameter is your language specific CodeCompletionContext */ template struct CodeCompletionItemTester { using Element = QExplicitlySharedDataPointer; using Item = QExplicitlySharedDataPointer; using Context = QExplicitlySharedDataPointer; //Standard constructor - CodeCompletionItemTester(DUContext* context, const QString& text = "; ", const QString& followingText = QString(), + CodeCompletionItemTester(DUContext* context, const QString& text = QStringLiteral("; "), const QString& followingText = QString(), const CursorInRevision& position = CursorInRevision::invalid()) : completionContext(new T(DUContextPointer(context), text, followingText, position.isValid() ? position : context->range().end)) { init(); } //Can be used if you already have the completion context CodeCompletionItemTester(const Context& context) : completionContext(context) { init(); } //Creates a CodeCompletionItemTester for the parent context CodeCompletionItemTester parent() const { Context parent = Context(dynamic_cast(completionContext->parentContext())); Q_ASSERT(parent); return CodeCompletionItemTester(parent); } void addElements(const QList& elements) { for (auto& element : elements) { Item item(dynamic_cast(element.data())); if(item) items << item; CompletionTreeNode* node = dynamic_cast(element.data()); if(node) addElements(node->children); } } bool containsDeclaration(Declaration* dec) const { for (auto& item : items) { if (item->declaration().data() == dec) { return true; } } return false; } QList items; // All items retrieved QStringList names; // Names of all completion-items Context completionContext; //Convenience-function to retrieve data from completion-items by name QVariant itemData(const QString& itemName, int column = KTextEditor::CodeCompletionModel::Name, int role = Qt::DisplayRole) const { return itemData(names.indexOf(itemName), column, role); } QVariant itemData(int itemNumber, int column = KTextEditor::CodeCompletionModel::Name, int role = Qt::DisplayRole) const { if(itemNumber < 0 || itemNumber >= items.size()) return QVariant(); return itemData(items[itemNumber], column, role); } QVariant itemData(Item item, int column = KTextEditor::CodeCompletionModel::Name, int role = Qt::DisplayRole) const { return item->data(fakeModel().index(0, column), role, nullptr); } Item findItem(const QString& itemName) const { const auto idx = names.indexOf(itemName); if (idx < 0) { return {}; } return items[idx]; } private: void init() { if ( !completionContext || !completionContext->isValid() ) { qWarning() << "invalid completion context"; return; } bool abort = false; items = completionContext->completionItems(abort); addElements(completionContext->ungroupedElements()); names.reserve(items.size()); foreach(Item i, items) { names << i->data(fakeModel().index(0, KTextEditor::CodeCompletionModel::Name), Qt::DisplayRole, nullptr).toString(); } } static QStandardItemModel& fakeModel() { static QStandardItemModel model; model.setColumnCount(10); model.setRowCount(10); return model; } }; /** * Helper class that inserts the given text into the duchain under the specified name, * allows parsing it with a simple call to parse(), and automatically releases the top-context * * The duchain must not be locked when this object is destroyed */ struct InsertIntoDUChain { ///Artificially inserts a file called @p name with the text @p text InsertIntoDUChain(const QString& name, const QString& text) : m_insertedCode(IndexedString(name), text), m_topContext(nullptr) { } ~InsertIntoDUChain() { get(); release(); } ///The duchain must not be locked when this is called void release() { if(m_topContext) { DUChainWriteLocker lock; m_topContext = nullptr; const QList chains = DUChain::self()->chainsForDocument(m_insertedCode.file()); for (TopDUContext* top : chains) { DUChain::self()->removeDocumentChain(top); } } } TopDUContext* operator->() { get(); return m_topContext.data(); } TopDUContext* tryGet() { DUChainReadLocker lock; return DUChain::self()->chainForDocument(m_insertedCode.file(), false); } void get() { if(!m_topContext) m_topContext = tryGet(); } ///Helper function: get a declaration based on its qualified identifier Declaration* getDeclaration(const QString& id) { get(); if(!topContext()) return nullptr; return DeclarationId(IndexedQualifiedIdentifier(QualifiedIdentifier(id))).getDeclaration(topContext()); } TopDUContext* topContext() { return m_topContext.data(); } /** * Parses this inserted code as a stand-alone top-context * The duchain must not be locked when this is called * * @param features The features that should be requested for the top-context * @param update Whether the top-context should be updated if it already exists. Else it will be deleted. */ void parse(uint features = TopDUContext::AllDeclarationsContextsAndUses, bool update = false) { if(!update) release(); m_topContext = DUChain::self()->waitForUpdate(m_insertedCode.file(), (TopDUContext::Features)features, false); Q_ASSERT(m_topContext); DUChainReadLocker lock; Q_ASSERT(!m_topContext->parsingEnvironmentFile()->isProxyContext()); } InsertArtificialCodeRepresentation m_insertedCode; ReferencedTopDUContext m_topContext; }; #endif // KDEVPLATFORM_CODECOMPLETIONTESTHELPER_H