Refactor CppElementEvaluator

Separate the use of CppElementEvaluator for CppHoverHandler from
the use for CppTypeHierarchyWidget. They are in fact much
different things.

Fix CppHoverHandler (enabled when ClangCodeModel plugin is disabled)
showing tooltips for symbols other than class or template.
Fix CppHoverHandler showing full template arguments for typedefs.

Change-Id: I5c44016014749d0d958b91a9a1ee9b35d3ea5eaa
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Jarek Kobus
2021-01-06 15:28:21 +01:00
parent 661193f67b
commit 0e7774e75d
3 changed files with 337 additions and 305 deletions

View File

@@ -217,10 +217,7 @@ void CppTypeHierarchyWidget::perform()
showProgress(); showProgress();
CppElementEvaluator evaluator(widget); m_future = CppElementEvaluator::asyncExecute(widget);
evaluator.setLookupBaseClasses(true);
evaluator.setLookupDerivedClasses(true);
m_future = evaluator.asyncExecute();
m_futureWatcher.setFuture(QFuture<void>(m_future)); m_futureWatcher.setFuture(QFuture<void>(m_future));
m_synchronizer.addFuture(QFuture<void>(m_future)); m_synchronizer.addFuture(QFuture<void>(m_future));
@@ -238,11 +235,7 @@ void CppTypeHierarchyWidget::performFromExpression(const QString &expression, co
showProgress(); showProgress();
CppElementEvaluator evaluator(nullptr); m_future = CppElementEvaluator::asyncExecute(expression, fileName);
evaluator.setLookupBaseClasses(true);
evaluator.setLookupDerivedClasses(true);
evaluator.setExpression(expression, fileName);
m_future = evaluator.asyncExpressionExecute();
m_futureWatcher.setFuture(QFuture<void>(m_future)); m_futureWatcher.setFuture(QFuture<void>(m_future));
m_synchronizer.addFuture(QFuture<void>(m_future)); m_synchronizer.addFuture(QFuture<void>(m_future));

View File

@@ -46,14 +46,6 @@ using namespace CPlusPlus;
namespace CppTools { namespace CppTools {
static void handleLookupItemMatch(QFutureInterface<QSharedPointer<CppElement>> &futureInterface,
const Snapshot &snapshot,
const LookupItem &lookupItem,
const LookupContext &context,
SymbolFinder symbolFinder,
bool lookupBaseClasses,
bool lookupDerivedClasses);
static QStringList stripName(const QString &name) static QStringList stripName(const QString &name)
{ {
QStringList all; QStringList all;
@@ -130,6 +122,7 @@ CppDeclarableElement::CppDeclarableElement(Symbol *declaration)
Overview overview; Overview overview;
overview.showArgumentNames = true; overview.showArgumentNames = true;
overview.showReturnTypes = true; overview.showReturnTypes = true;
overview.showTemplateParameters = true;
name = overview.prettyName(declaration->name()); name = overview.prettyName(declaration->name());
if (declaration->enclosingScope()->isClass() || if (declaration->enclosingScope()->isClass() ||
declaration->enclosingScope()->isNamespace() || declaration->enclosingScope()->isNamespace() ||
@@ -158,7 +151,6 @@ public:
} }
}; };
CppClass::CppClass(Symbol *declaration) : CppDeclarableElement(declaration) CppClass::CppClass(Symbol *declaration) : CppDeclarableElement(declaration)
{ {
helpCategory = Core::HelpItem::ClassOrNamespace; helpCategory = Core::HelpItem::ClassOrNamespace;
@@ -274,7 +266,9 @@ public:
: CppDeclarableElement(declaration) : CppDeclarableElement(declaration)
{ {
helpCategory = Core::HelpItem::Typedef; helpCategory = Core::HelpItem::Typedef;
tooltip = Overview().prettyType(declaration->type(), qualifiedName); Overview overview;
overview.showTemplateParameters = true;
tooltip = overview.prettyType(declaration->type(), qualifiedName);
} }
}; };
@@ -348,27 +342,109 @@ public:
} }
}; };
CppElementEvaluator::CppElementEvaluator(TextEditor::TextEditorWidget *editor) : static bool isCppClass(Symbol *symbol)
m_editor(editor),
m_modelManager(CppModelManager::instance()),
m_tc(editor ? editor->textCursor() : QTextCursor()),
m_lookupBaseClasses(false),
m_lookupDerivedClasses(false)
{}
void CppElementEvaluator::setTextCursor(const QTextCursor &tc)
{ m_tc = tc; }
void CppElementEvaluator::setLookupBaseClasses(const bool lookup)
{ m_lookupBaseClasses = lookup; }
void CppElementEvaluator::setLookupDerivedClasses(const bool lookup)
{ m_lookupDerivedClasses = lookup; }
void CppElementEvaluator::setExpression(const QString &expression, const QString &fileName)
{ {
m_expression = expression; return symbol->isClass() || symbol->isForwardClassDeclaration()
m_fileName = fileName; || (symbol->isTemplate() && symbol->asTemplate()->declaration()
&& (symbol->asTemplate()->declaration()->isClass()
|| symbol->asTemplate()->declaration()->isForwardClassDeclaration()));
}
static Symbol *followClassDeclaration(Symbol *symbol, const Snapshot &snapshot, SymbolFinder symbolFinder,
LookupContext *context = nullptr)
{
if (!symbol->isForwardClassDeclaration())
return symbol;
Symbol *classDeclaration = symbolFinder.findMatchingClassDeclaration(symbol, snapshot);
if (!classDeclaration)
return symbol;
if (context) {
const QString fileName = QString::fromUtf8(classDeclaration->fileName(),
classDeclaration->fileNameLength());
const Document::Ptr declarationDocument = snapshot.document(fileName);
if (declarationDocument != context->thisDocument())
(*context) = LookupContext(declarationDocument, snapshot);
}
return classDeclaration;
}
static Symbol *followTemplateAsClass(Symbol *symbol)
{
if (Template *t = symbol->asTemplate(); t && t->declaration() && t->declaration()->asClass())
return t->declaration()->asClass();
return symbol;
}
static void createTypeHierarchy(QFutureInterface<QSharedPointer<CppElement>> &futureInterface,
const Snapshot &snapshot,
const LookupItem &lookupItem,
const LookupContext &context,
SymbolFinder symbolFinder)
{
if (futureInterface.isCanceled())
return;
Symbol *declaration = lookupItem.declaration();
if (!declaration)
return;
if (!isCppClass(declaration))
return;
LookupContext contextToUse = context;
declaration = followClassDeclaration(declaration, snapshot, symbolFinder, &contextToUse);
declaration = followTemplateAsClass(declaration);
if (futureInterface.isCanceled())
return;
QSharedPointer<CppClass> cppClass(new CppClass(declaration));
cppClass->lookupBases(futureInterface, declaration, contextToUse);
if (futureInterface.isCanceled())
return;
cppClass->lookupDerived(futureInterface, declaration, snapshot);
if (futureInterface.isCanceled())
return;
futureInterface.reportResult(cppClass);
}
static QSharedPointer<CppElement> handleLookupItemMatch(const Snapshot &snapshot,
const LookupItem &lookupItem,
const LookupContext &context,
SymbolFinder symbolFinder)
{
QSharedPointer<CppElement> element;
Symbol *declaration = lookupItem.declaration();
if (!declaration) {
const QString &type = Overview().prettyType(lookupItem.type(), QString());
element = QSharedPointer<CppElement>(new Unknown(type));
} else {
const FullySpecifiedType &type = declaration->type();
if (declaration->isNamespace()) {
element = QSharedPointer<CppElement>(new CppNamespace(declaration));
} else if (isCppClass(declaration)) {
LookupContext contextToUse = context;
declaration = followClassDeclaration(declaration, snapshot, symbolFinder, &contextToUse);
element = QSharedPointer<CppElement>(new CppClass(declaration));
} else if (Enum *enumDecl = declaration->asEnum()) {
element = QSharedPointer<CppElement>(new CppEnum(enumDecl));
} else if (auto enumerator = dynamic_cast<EnumeratorDeclaration *>(declaration)) {
element = QSharedPointer<CppElement>(new CppEnumerator(enumerator));
} else if (declaration->isTypedef()) {
element = QSharedPointer<CppElement>(new CppTypedef(declaration));
} else if (declaration->isFunction()
|| (type.isValid() && type->isFunctionType())
|| declaration->isTemplate()) {
element = QSharedPointer<CppElement>(new CppFunction(declaration));
} else if (declaration->isDeclaration() && type.isValid()) {
element = QSharedPointer<CppElement>(
new CppVariable(declaration, context, lookupItem.scope()));
} else {
element = QSharedPointer<CppElement>(new CppDeclarableElement(declaration));
}
}
return element;
} }
// special case for bug QTCREATORBUG-4780 // special case for bug QTCREATORBUG-4780
@@ -378,20 +454,13 @@ static bool shouldOmitElement(const LookupItem &lookupItem, const Scope *scope)
&& lookupItem.type().match(scope->asFunction()->returnType()); && lookupItem.type().match(scope->asFunction()->returnType());
} }
void CppElementEvaluator::execute() using namespace std::placeholders;
{ using ExecFunction = std::function<QFuture<QSharedPointer<CppElement>>
execute(&CppElementEvaluator::sourceDataFromGui, &CppElementEvaluator::syncExec); (const CPlusPlus::Snapshot &, const CPlusPlus::LookupItem &,
} const CPlusPlus::LookupContext &)>;
using SourceFunction = std::function<bool(const CPlusPlus::Snapshot &,
QFuture<QSharedPointer<CppElement>> CppElementEvaluator::asyncExecute() CPlusPlus::Document::Ptr &,
{ CPlusPlus::Scope **, QString &)>;
return execute(&CppElementEvaluator::sourceDataFromGui, &CppElementEvaluator::asyncExec);
}
QFuture<QSharedPointer<CppElement>> CppElementEvaluator::asyncExpressionExecute()
{
return execute(&CppElementEvaluator::sourceDataFromExpression, &CppElementEvaluator::asyncExec);
}
static QFuture<QSharedPointer<CppElement>> createFinishedFuture() static QFuture<QSharedPointer<CppElement>> createFinishedFuture()
{ {
@@ -401,8 +470,111 @@ static QFuture<QSharedPointer<CppElement>> createFinishedFuture()
return futureInterface.future(); return futureInterface.future();
} }
bool CppElementEvaluator::sourceDataFromGui(const CPlusPlus::Snapshot &snapshot, static LookupItem findLookupItem(const CPlusPlus::Snapshot &snapshot, CPlusPlus::Document::Ptr &doc,
Document::Ptr &doc, Scope **scope, QString &expression) Scope *scope, const QString &expression, LookupContext *lookupContext, bool followTypedef)
{
TypeOfExpression typeOfExpression;
typeOfExpression.init(doc, snapshot);
// make possible to instantiate templates
typeOfExpression.setExpandTemplates(true);
const QList<LookupItem> &lookupItems = typeOfExpression(expression.toUtf8(), scope);
*lookupContext = typeOfExpression.context();
if (lookupItems.isEmpty())
return LookupItem();
auto isInteresting = [followTypedef](Symbol *symbol) {
return symbol && (!followTypedef || (symbol->isClass() || symbol->isTemplate()
|| symbol->isForwardClassDeclaration() || symbol->isTypedef()));
};
for (const LookupItem &item : lookupItems) {
if (shouldOmitElement(item, scope))
continue;
Symbol *symbol = item.declaration();
if (!isInteresting(symbol))
continue;
if (followTypedef && symbol->isTypedef()) {
CPlusPlus::NamedType *namedType = symbol->type()->asNamedType();
if (!namedType) {
// Anonymous aggregate such as: typedef struct {} Empty;
continue;
}
return TypeHierarchyBuilder::followTypedef(*lookupContext,
namedType->name(), symbol->enclosingScope());
}
return item;
}
return LookupItem();
}
static QFuture<QSharedPointer<CppElement>> exec(SourceFunction &&sourceFunction,
ExecFunction &&execFunction,
bool followTypedef = true)
{
const Snapshot &snapshot = CppModelManager::instance()->snapshot();
Document::Ptr doc;
QString expression;
Scope *scope = nullptr;
if (!std::invoke(std::forward<SourceFunction>(sourceFunction), snapshot, doc, &scope, expression))
return createFinishedFuture();
LookupContext lookupContext;
const LookupItem &lookupItem = findLookupItem(snapshot, doc, scope, expression, &lookupContext,
followTypedef);
if (!lookupItem.declaration())
return createFinishedFuture();
return std::invoke(std::forward<ExecFunction>(execFunction), snapshot, lookupItem, lookupContext);
}
static QFuture<QSharedPointer<CppElement>> asyncExec(
const CPlusPlus::Snapshot &snapshot, const CPlusPlus::LookupItem &lookupItem,
const CPlusPlus::LookupContext &lookupContext)
{
return Utils::runAsync(&createTypeHierarchy, snapshot, lookupItem, lookupContext,
*CppModelManager::instance()->symbolFinder());
}
class FromExpressionFunctor
{
public:
FromExpressionFunctor(const QString &expression, const QString &fileName)
: m_expression(expression)
, m_fileName(fileName)
{}
bool operator()(const CPlusPlus::Snapshot &snapshot, Document::Ptr &doc, Scope **scope,
QString &expression)
{
doc = snapshot.document(m_fileName);
expression = m_expression;
// Fetch the expression's code
*scope = doc->globalNamespace();
return true;
}
private:
const QString m_expression;
const QString m_fileName;
};
QFuture<QSharedPointer<CppElement>> CppElementEvaluator::asyncExecute(const QString &expression,
const QString &fileName)
{
return exec(FromExpressionFunctor(expression, fileName), asyncExec);
}
class FromGuiFunctor
{
public:
FromGuiFunctor(TextEditor::TextEditorWidget *editor)
: m_editor(editor)
, m_tc(editor->textCursor())
{}
bool operator()(const CPlusPlus::Snapshot &snapshot, Document::Ptr &doc, Scope **scope,
QString &expression)
{ {
doc = snapshot.document(m_editor->textDocument()->filePath()); doc = snapshot.document(m_editor->textDocument()->filePath());
if (!doc) if (!doc)
@@ -426,98 +598,37 @@ bool CppElementEvaluator::sourceDataFromGui(const CPlusPlus::Snapshot &snapshot,
*scope = doc->scopeAt(line, column - 1); *scope = doc->scopeAt(line, column - 1);
return true; return true;
} }
QFuture<QSharedPointer<CppElement>> syncExec(const CPlusPlus::Snapshot &,
const CPlusPlus::LookupItem &, const CPlusPlus::LookupContext &);
bool CppElementEvaluator::sourceDataFromExpression(const CPlusPlus::Snapshot &snapshot, private:
Document::Ptr &doc, Scope **scope, QString &expression) void checkDiagnosticMessage(int pos);
{ bool matchIncludeFile(const CPlusPlus::Document::Ptr &document, int line);
doc = snapshot.document(m_fileName); bool matchMacroInUse(const CPlusPlus::Document::Ptr &document, int pos);
expression = m_expression;
// Fetch the expression's code public:
*scope = doc->globalNamespace(); void clear();
return true;
}
// @todo: Consider refactoring code from CppEditor::findLinkAt into here. TextEditor::TextEditorWidget *m_editor;
QFuture<QSharedPointer<CppElement>> CppElementEvaluator::execute(SourceFunction sourceFunction, QTextCursor m_tc;
ExecFunction execFuntion) QSharedPointer<CppElement> m_element;
{ QString m_diagnosis;
clear(); };
if (!m_modelManager) QFuture<QSharedPointer<CppElement>> FromGuiFunctor::syncExec(
return createFinishedFuture();
const Snapshot &snapshot = m_modelManager->snapshot();
Document::Ptr doc;
QString expression;
Scope *scope = nullptr;
if (!std::invoke(sourceFunction, this, snapshot, doc, &scope, expression))
return createFinishedFuture();
TypeOfExpression typeOfExpression;
typeOfExpression.init(doc, snapshot);
// make possible to instantiate templates
typeOfExpression.setExpandTemplates(true);
const QList<LookupItem> &lookupItems = typeOfExpression(expression.toUtf8(), scope);
if (lookupItems.isEmpty())
return createFinishedFuture();
LookupItem lookupItem;
for (const LookupItem &item : lookupItems) {
if (shouldOmitElement(item, scope))
continue;
Symbol *symbol = item.declaration();
if (!symbol)
continue;
if (!symbol->isClass() && !symbol->isTemplate() && !symbol->isForwardClassDeclaration() && !symbol->isTypedef())
continue;
if (symbol->isTypedef()) {
CPlusPlus::NamedType *namedType = symbol->type()->asNamedType();
if (!namedType) {
// Anonymous aggregate such as: typedef struct {} Empty;
continue;
}
lookupItem = TypeHierarchyBuilder::followTypedef(typeOfExpression.context(),
namedType->name(), symbol->enclosingScope());
} else {
lookupItem = item;
}
break;
}
if (!lookupItem.declaration())
return createFinishedFuture();
return std::invoke(execFuntion, this, snapshot, lookupItem, typeOfExpression.context());
}
QFuture<QSharedPointer<CppElement>> CppElementEvaluator::syncExec(
const CPlusPlus::Snapshot &snapshot, const CPlusPlus::LookupItem &lookupItem, const CPlusPlus::Snapshot &snapshot, const CPlusPlus::LookupItem &lookupItem,
const CPlusPlus::LookupContext &lookupContext) const CPlusPlus::LookupContext &lookupContext)
{ {
QFutureInterface<QSharedPointer<CppElement>> futureInterface; QFutureInterface<QSharedPointer<CppElement>> futureInterface;
futureInterface.reportStarted(); futureInterface.reportStarted();
handleLookupItemMatch(futureInterface, snapshot, lookupItem, lookupContext, m_element = handleLookupItemMatch(snapshot, lookupItem, lookupContext,
*m_modelManager->symbolFinder(), *CppModelManager::instance()->symbolFinder());
m_lookupBaseClasses, m_lookupDerivedClasses); futureInterface.reportResult(m_element);
futureInterface.reportFinished(); futureInterface.reportFinished();
QFuture<QSharedPointer<CppElement>> future = futureInterface.future(); return futureInterface.future();
m_element = future.result();
return future;
} }
QFuture<QSharedPointer<CppElement>> CppElementEvaluator::asyncExec( void FromGuiFunctor::checkDiagnosticMessage(int pos)
const CPlusPlus::Snapshot &snapshot, const CPlusPlus::LookupItem &lookupItem,
const CPlusPlus::LookupContext &lookupContext)
{
return Utils::runAsync(&handleLookupItemMatch, snapshot, lookupItem, lookupContext,
*m_modelManager->symbolFinder(),
m_lookupBaseClasses, m_lookupDerivedClasses);
}
void CppElementEvaluator::checkDiagnosticMessage(int pos)
{ {
foreach (const QTextEdit::ExtraSelection &sel, foreach (const QTextEdit::ExtraSelection &sel,
m_editor->extraSelections(TextEditor::TextEditorWidget::CodeWarningsSelection)) { m_editor->extraSelections(TextEditor::TextEditorWidget::CodeWarningsSelection)) {
@@ -528,9 +639,10 @@ void CppElementEvaluator::checkDiagnosticMessage(int pos)
} }
} }
bool CppElementEvaluator::matchIncludeFile(const Document::Ptr &document, int line) bool FromGuiFunctor::matchIncludeFile(const Document::Ptr &document, int line)
{ {
foreach (const Document::Include &includeFile, document->resolvedIncludes()) { const QList<Document::Include> &includes = document->resolvedIncludes();
for (const Document::Include &includeFile : includes) {
if (includeFile.line() == line) { if (includeFile.line() == line) {
m_element = QSharedPointer<CppElement>(new CppInclude(includeFile)); m_element = QSharedPointer<CppElement>(new CppInclude(includeFile));
return true; return true;
@@ -539,9 +651,10 @@ bool CppElementEvaluator::matchIncludeFile(const Document::Ptr &document, int li
return false; return false;
} }
bool CppElementEvaluator::matchMacroInUse(const Document::Ptr &document, int pos) bool FromGuiFunctor::matchMacroInUse(const Document::Ptr &document, int pos)
{ {
foreach (const Document::MacroUse &use, document->macroUses()) { const QList<Document::MacroUse> macros = document->macroUses();
for (const Document::MacroUse &use : macros) {
if (use.containsUtf16charOffset(pos)) { if (use.containsUtf16charOffset(pos)) {
const int begin = use.utf16charsBegin(); const int begin = use.utf16charsBegin();
if (pos < begin + use.macro().nameToQString().size()) { if (pos < begin + use.macro().nameToQString().size()) {
@@ -553,104 +666,63 @@ bool CppElementEvaluator::matchMacroInUse(const Document::Ptr &document, int pos
return false; return false;
} }
static void handleLookupItemMatch(QFutureInterface<QSharedPointer<CppElement>> &futureInterface, void FromGuiFunctor::clear()
const Snapshot &snapshot,
const LookupItem &lookupItem,
const LookupContext &context,
SymbolFinder symbolFinder,
bool lookupBaseClasses,
bool lookupDerivedClasses)
{ {
if (futureInterface.isCanceled()) m_element.clear();
return; m_diagnosis.clear();
QSharedPointer<CppElement> element;
Symbol *declaration = lookupItem.declaration();
if (!declaration) {
const QString &type = Overview().prettyType(lookupItem.type(), QString());
element = QSharedPointer<CppElement>(new Unknown(type));
} else {
const FullySpecifiedType &type = declaration->type();
if (declaration->isNamespace()) {
element = QSharedPointer<CppElement>(new CppNamespace(declaration));
} else if (declaration->isClass()
|| declaration->isForwardClassDeclaration()
|| (declaration->isTemplate() && declaration->asTemplate()->declaration()
&& (declaration->asTemplate()->declaration()->isClass()
|| declaration->asTemplate()->declaration()->isForwardClassDeclaration()))) {
LookupContext contextToUse = context;
if (declaration->isForwardClassDeclaration()) {
Symbol *classDeclaration = symbolFinder.findMatchingClassDeclaration(declaration,
snapshot);
if (classDeclaration) {
declaration = classDeclaration;
const QString fileName = QString::fromUtf8(declaration->fileName(),
declaration->fileNameLength());
const Document::Ptr declarationDocument = snapshot.document(fileName);
if (declarationDocument != context.thisDocument())
contextToUse = LookupContext(declarationDocument, snapshot);
}
} }
if (declaration->asTemplate() && declaration->asTemplate()->declaration() class CppElementEvaluatorPrivate
&& declaration->asTemplate()->declaration()->asClass()) {
declaration = declaration->asTemplate()->declaration()->asClass(); public:
CppElementEvaluatorPrivate(TextEditor::TextEditorWidget *editor) : m_functor(editor) {}
FromGuiFunctor m_functor;
};
if (futureInterface.isCanceled()) CppElementEvaluator::CppElementEvaluator(TextEditor::TextEditorWidget *editor)
return; : d(new CppElementEvaluatorPrivate(editor))
QSharedPointer<CppClass> cppClass(new CppClass(declaration)); {}
if (lookupBaseClasses)
cppClass->lookupBases(futureInterface, declaration, contextToUse); CppElementEvaluator::~CppElementEvaluator()
if (futureInterface.isCanceled()) {
return; delete d;
if (lookupDerivedClasses)
cppClass->lookupDerived(futureInterface, declaration, snapshot);
if (futureInterface.isCanceled())
return;
element = cppClass;
} else if (Enum *enumDecl = declaration->asEnum()) {
element = QSharedPointer<CppElement>(new CppEnum(enumDecl));
} else if (auto enumerator = dynamic_cast<EnumeratorDeclaration *>(declaration)) {
element = QSharedPointer<CppElement>(new CppEnumerator(enumerator));
} else if (declaration->isTypedef()) {
element = QSharedPointer<CppElement>(new CppTypedef(declaration));
} else if (declaration->isFunction()
|| (type.isValid() && type->isFunctionType())
|| declaration->isTemplate()) {
element = QSharedPointer<CppElement>(new CppFunction(declaration));
} else if (declaration->isDeclaration() && type.isValid()) {
element = QSharedPointer<CppElement>(
new CppVariable(declaration, context, lookupItem.scope()));
} else {
element = QSharedPointer<CppElement>(new CppDeclarableElement(declaration));
} }
void CppElementEvaluator::setTextCursor(const QTextCursor &tc)
{
d->m_functor.m_tc = tc;
} }
futureInterface.reportResult(element);
QFuture<QSharedPointer<CppElement>> CppElementEvaluator::asyncExecute(
TextEditor::TextEditorWidget *editor)
{
return exec(FromGuiFunctor(editor), asyncExec);
}
void CppElementEvaluator::execute()
{
d->m_functor.clear();
exec(std::ref(d->m_functor), std::bind(&FromGuiFunctor::syncExec, &d->m_functor, _1, _2, _3), false);
} }
bool CppElementEvaluator::identifiedCppElement() const bool CppElementEvaluator::identifiedCppElement() const
{ {
return !m_element.isNull(); return !d->m_functor.m_element.isNull();
} }
const QSharedPointer<CppElement> &CppElementEvaluator::cppElement() const const QSharedPointer<CppElement> &CppElementEvaluator::cppElement() const
{ {
return m_element; return d->m_functor.m_element;
} }
bool CppElementEvaluator::hasDiagnosis() const bool CppElementEvaluator::hasDiagnosis() const
{ {
return !m_diagnosis.isEmpty(); return !d->m_functor.m_diagnosis.isEmpty();
} }
const QString &CppElementEvaluator::diagnosis() const const QString &CppElementEvaluator::diagnosis() const
{ {
return m_diagnosis; return d->m_functor.m_diagnosis;
}
void CppElementEvaluator::clear()
{
m_element.clear();
m_diagnosis.clear();
} }
Utils::Link CppElementEvaluator::linkFromExpression(const QString &expression, const QString &fileName) Utils::Link CppElementEvaluator::linkFromExpression(const QString &expression, const QString &fileName)

View File

@@ -39,6 +39,8 @@
#include <QStringList> #include <QStringList>
#include <QTextCursor> #include <QTextCursor>
#include <functional>
namespace CPlusPlus { namespace CPlusPlus {
class LookupItem; class LookupItem;
class LookupContext; class LookupContext;
@@ -48,19 +50,18 @@ namespace CppTools {
class CppElement; class CppElement;
class CppModelManager; class CppModelManager;
class CPPTOOLS_EXPORT CppElementEvaluator class CPPTOOLS_EXPORT CppElementEvaluator final
{ {
public: public:
explicit CppElementEvaluator(TextEditor::TextEditorWidget *editor); explicit CppElementEvaluator(TextEditor::TextEditorWidget *editor);
~CppElementEvaluator();
void setTextCursor(const QTextCursor &tc); void setTextCursor(const QTextCursor &tc);
void setLookupBaseClasses(const bool lookup);
void setLookupDerivedClasses(const bool lookup);
void setExpression(const QString &expression, const QString &fileName);
void execute(); void execute();
QFuture<QSharedPointer<CppElement>> asyncExecute(); static QFuture<QSharedPointer<CppElement>> asyncExecute(TextEditor::TextEditorWidget *editor);
QFuture<QSharedPointer<CppElement>> asyncExpressionExecute(); static QFuture<QSharedPointer<CppElement>> asyncExecute(const QString &expression,
const QString &fileName);
bool identifiedCppElement() const; bool identifiedCppElement() const;
const QSharedPointer<CppElement> &cppElement() const; const QSharedPointer<CppElement> &cppElement() const;
bool hasDiagnosis() const; bool hasDiagnosis() const;
@@ -69,41 +70,7 @@ public:
static Utils::Link linkFromExpression(const QString &expression, const QString &fileName); static Utils::Link linkFromExpression(const QString &expression, const QString &fileName);
private: private:
void clear(); class CppElementEvaluatorPrivate *d;
using ExecFunction = QFuture<QSharedPointer<CppElement>>(CppElementEvaluator::*)
(const CPlusPlus::Snapshot &, const CPlusPlus::LookupItem &,
const CPlusPlus::LookupContext &);
using SourceFunction = bool(CppElementEvaluator::*)
(const CPlusPlus::Snapshot &, CPlusPlus::Document::Ptr &,
CPlusPlus::Scope **, QString &);
QFuture<QSharedPointer<CppElement>> execute(SourceFunction sourceFunction,
ExecFunction execFuntion);
QFuture<QSharedPointer<CppElement>> syncExec(const CPlusPlus::Snapshot &,
const CPlusPlus::LookupItem &, const CPlusPlus::LookupContext &);
QFuture<QSharedPointer<CppElement>> asyncExec(const CPlusPlus::Snapshot &,
const CPlusPlus::LookupItem &, const CPlusPlus::LookupContext &);
bool sourceDataFromGui(const CPlusPlus::Snapshot &snapshot,
CPlusPlus::Document::Ptr &doc,
CPlusPlus::Scope **scope,
QString &expression);
bool sourceDataFromExpression(const CPlusPlus::Snapshot &snapshot,
CPlusPlus::Document::Ptr &doc,
CPlusPlus::Scope **scope,
QString &expression);
void checkDiagnosticMessage(int pos);
bool matchIncludeFile(const CPlusPlus::Document::Ptr &document, int line);
bool matchMacroInUse(const CPlusPlus::Document::Ptr &document, int pos);
TextEditor::TextEditorWidget *m_editor;
CppTools::CppModelManager *m_modelManager;
QTextCursor m_tc;
QString m_expression;
QString m_fileName;
bool m_lookupBaseClasses;
bool m_lookupDerivedClasses;
QSharedPointer<CppElement> m_element;
QString m_diagnosis;
}; };
class CppClass; class CppClass;