forked from qt-creator/qt-creator
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:
@@ -217,10 +217,7 @@ void CppTypeHierarchyWidget::perform()
|
||||
|
||||
showProgress();
|
||||
|
||||
CppElementEvaluator evaluator(widget);
|
||||
evaluator.setLookupBaseClasses(true);
|
||||
evaluator.setLookupDerivedClasses(true);
|
||||
m_future = evaluator.asyncExecute();
|
||||
m_future = CppElementEvaluator::asyncExecute(widget);
|
||||
m_futureWatcher.setFuture(QFuture<void>(m_future));
|
||||
m_synchronizer.addFuture(QFuture<void>(m_future));
|
||||
|
||||
@@ -238,11 +235,7 @@ void CppTypeHierarchyWidget::performFromExpression(const QString &expression, co
|
||||
|
||||
showProgress();
|
||||
|
||||
CppElementEvaluator evaluator(nullptr);
|
||||
evaluator.setLookupBaseClasses(true);
|
||||
evaluator.setLookupDerivedClasses(true);
|
||||
evaluator.setExpression(expression, fileName);
|
||||
m_future = evaluator.asyncExpressionExecute();
|
||||
m_future = CppElementEvaluator::asyncExecute(expression, fileName);
|
||||
m_futureWatcher.setFuture(QFuture<void>(m_future));
|
||||
m_synchronizer.addFuture(QFuture<void>(m_future));
|
||||
|
||||
|
||||
@@ -46,14 +46,6 @@ using namespace CPlusPlus;
|
||||
|
||||
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)
|
||||
{
|
||||
QStringList all;
|
||||
@@ -130,6 +122,7 @@ CppDeclarableElement::CppDeclarableElement(Symbol *declaration)
|
||||
Overview overview;
|
||||
overview.showArgumentNames = true;
|
||||
overview.showReturnTypes = true;
|
||||
overview.showTemplateParameters = true;
|
||||
name = overview.prettyName(declaration->name());
|
||||
if (declaration->enclosingScope()->isClass() ||
|
||||
declaration->enclosingScope()->isNamespace() ||
|
||||
@@ -158,7 +151,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
CppClass::CppClass(Symbol *declaration) : CppDeclarableElement(declaration)
|
||||
{
|
||||
helpCategory = Core::HelpItem::ClassOrNamespace;
|
||||
@@ -274,7 +266,9 @@ public:
|
||||
: CppDeclarableElement(declaration)
|
||||
{
|
||||
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) :
|
||||
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)
|
||||
static bool isCppClass(Symbol *symbol)
|
||||
{
|
||||
m_expression = expression;
|
||||
m_fileName = fileName;
|
||||
return symbol->isClass() || symbol->isForwardClassDeclaration()
|
||||
|| (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
|
||||
@@ -378,20 +454,13 @@ static bool shouldOmitElement(const LookupItem &lookupItem, const Scope *scope)
|
||||
&& lookupItem.type().match(scope->asFunction()->returnType());
|
||||
}
|
||||
|
||||
void CppElementEvaluator::execute()
|
||||
{
|
||||
execute(&CppElementEvaluator::sourceDataFromGui, &CppElementEvaluator::syncExec);
|
||||
}
|
||||
|
||||
QFuture<QSharedPointer<CppElement>> CppElementEvaluator::asyncExecute()
|
||||
{
|
||||
return execute(&CppElementEvaluator::sourceDataFromGui, &CppElementEvaluator::asyncExec);
|
||||
}
|
||||
|
||||
QFuture<QSharedPointer<CppElement>> CppElementEvaluator::asyncExpressionExecute()
|
||||
{
|
||||
return execute(&CppElementEvaluator::sourceDataFromExpression, &CppElementEvaluator::asyncExec);
|
||||
}
|
||||
using namespace std::placeholders;
|
||||
using ExecFunction = std::function<QFuture<QSharedPointer<CppElement>>
|
||||
(const CPlusPlus::Snapshot &, const CPlusPlus::LookupItem &,
|
||||
const CPlusPlus::LookupContext &)>;
|
||||
using SourceFunction = std::function<bool(const CPlusPlus::Snapshot &,
|
||||
CPlusPlus::Document::Ptr &,
|
||||
CPlusPlus::Scope **, QString &)>;
|
||||
|
||||
static QFuture<QSharedPointer<CppElement>> createFinishedFuture()
|
||||
{
|
||||
@@ -401,8 +470,111 @@ static QFuture<QSharedPointer<CppElement>> createFinishedFuture()
|
||||
return futureInterface.future();
|
||||
}
|
||||
|
||||
bool CppElementEvaluator::sourceDataFromGui(const CPlusPlus::Snapshot &snapshot,
|
||||
Document::Ptr &doc, Scope **scope, QString &expression)
|
||||
static LookupItem findLookupItem(const CPlusPlus::Snapshot &snapshot, CPlusPlus::Document::Ptr &doc,
|
||||
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());
|
||||
if (!doc)
|
||||
@@ -426,98 +598,37 @@ bool CppElementEvaluator::sourceDataFromGui(const CPlusPlus::Snapshot &snapshot,
|
||||
*scope = doc->scopeAt(line, column - 1);
|
||||
return true;
|
||||
}
|
||||
QFuture<QSharedPointer<CppElement>> syncExec(const CPlusPlus::Snapshot &,
|
||||
const CPlusPlus::LookupItem &, const CPlusPlus::LookupContext &);
|
||||
|
||||
bool CppElementEvaluator::sourceDataFromExpression(const CPlusPlus::Snapshot &snapshot,
|
||||
Document::Ptr &doc, Scope **scope, QString &expression)
|
||||
{
|
||||
doc = snapshot.document(m_fileName);
|
||||
expression = m_expression;
|
||||
private:
|
||||
void checkDiagnosticMessage(int pos);
|
||||
bool matchIncludeFile(const CPlusPlus::Document::Ptr &document, int line);
|
||||
bool matchMacroInUse(const CPlusPlus::Document::Ptr &document, int pos);
|
||||
|
||||
// Fetch the expression's code
|
||||
*scope = doc->globalNamespace();
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
void clear();
|
||||
|
||||
// @todo: Consider refactoring code from CppEditor::findLinkAt into here.
|
||||
QFuture<QSharedPointer<CppElement>> CppElementEvaluator::execute(SourceFunction sourceFunction,
|
||||
ExecFunction execFuntion)
|
||||
{
|
||||
clear();
|
||||
TextEditor::TextEditorWidget *m_editor;
|
||||
QTextCursor m_tc;
|
||||
QSharedPointer<CppElement> m_element;
|
||||
QString m_diagnosis;
|
||||
};
|
||||
|
||||
if (!m_modelManager)
|
||||
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(
|
||||
QFuture<QSharedPointer<CppElement>> FromGuiFunctor::syncExec(
|
||||
const CPlusPlus::Snapshot &snapshot, const CPlusPlus::LookupItem &lookupItem,
|
||||
const CPlusPlus::LookupContext &lookupContext)
|
||||
{
|
||||
QFutureInterface<QSharedPointer<CppElement>> futureInterface;
|
||||
futureInterface.reportStarted();
|
||||
handleLookupItemMatch(futureInterface, snapshot, lookupItem, lookupContext,
|
||||
*m_modelManager->symbolFinder(),
|
||||
m_lookupBaseClasses, m_lookupDerivedClasses);
|
||||
m_element = handleLookupItemMatch(snapshot, lookupItem, lookupContext,
|
||||
*CppModelManager::instance()->symbolFinder());
|
||||
futureInterface.reportResult(m_element);
|
||||
futureInterface.reportFinished();
|
||||
QFuture<QSharedPointer<CppElement>> future = futureInterface.future();
|
||||
m_element = future.result();
|
||||
return future;
|
||||
return futureInterface.future();
|
||||
}
|
||||
|
||||
QFuture<QSharedPointer<CppElement>> CppElementEvaluator::asyncExec(
|
||||
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)
|
||||
void FromGuiFunctor::checkDiagnosticMessage(int pos)
|
||||
{
|
||||
foreach (const QTextEdit::ExtraSelection &sel,
|
||||
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) {
|
||||
m_element = QSharedPointer<CppElement>(new CppInclude(includeFile));
|
||||
return true;
|
||||
@@ -539,9 +651,10 @@ bool CppElementEvaluator::matchIncludeFile(const Document::Ptr &document, int li
|
||||
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)) {
|
||||
const int begin = use.utf16charsBegin();
|
||||
if (pos < begin + use.macro().nameToQString().size()) {
|
||||
@@ -553,104 +666,63 @@ bool CppElementEvaluator::matchMacroInUse(const Document::Ptr &document, int pos
|
||||
return false;
|
||||
}
|
||||
|
||||
static void handleLookupItemMatch(QFutureInterface<QSharedPointer<CppElement>> &futureInterface,
|
||||
const Snapshot &snapshot,
|
||||
const LookupItem &lookupItem,
|
||||
const LookupContext &context,
|
||||
SymbolFinder symbolFinder,
|
||||
bool lookupBaseClasses,
|
||||
bool lookupDerivedClasses)
|
||||
void FromGuiFunctor::clear()
|
||||
{
|
||||
if (futureInterface.isCanceled())
|
||||
return;
|
||||
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);
|
||||
}
|
||||
m_element.clear();
|
||||
m_diagnosis.clear();
|
||||
}
|
||||
|
||||
if (declaration->asTemplate() && declaration->asTemplate()->declaration()
|
||||
&& declaration->asTemplate()->declaration()->asClass())
|
||||
declaration = declaration->asTemplate()->declaration()->asClass();
|
||||
class CppElementEvaluatorPrivate
|
||||
{
|
||||
public:
|
||||
CppElementEvaluatorPrivate(TextEditor::TextEditorWidget *editor) : m_functor(editor) {}
|
||||
FromGuiFunctor m_functor;
|
||||
};
|
||||
|
||||
if (futureInterface.isCanceled())
|
||||
return;
|
||||
QSharedPointer<CppClass> cppClass(new CppClass(declaration));
|
||||
if (lookupBaseClasses)
|
||||
cppClass->lookupBases(futureInterface, declaration, contextToUse);
|
||||
if (futureInterface.isCanceled())
|
||||
return;
|
||||
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));
|
||||
CppElementEvaluator::CppElementEvaluator(TextEditor::TextEditorWidget *editor)
|
||||
: d(new CppElementEvaluatorPrivate(editor))
|
||||
{}
|
||||
|
||||
CppElementEvaluator::~CppElementEvaluator()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
return !m_element.isNull();
|
||||
return !d->m_functor.m_element.isNull();
|
||||
}
|
||||
|
||||
const QSharedPointer<CppElement> &CppElementEvaluator::cppElement() const
|
||||
{
|
||||
return m_element;
|
||||
return d->m_functor.m_element;
|
||||
}
|
||||
|
||||
bool CppElementEvaluator::hasDiagnosis() const
|
||||
{
|
||||
return !m_diagnosis.isEmpty();
|
||||
return !d->m_functor.m_diagnosis.isEmpty();
|
||||
}
|
||||
|
||||
const QString &CppElementEvaluator::diagnosis() const
|
||||
{
|
||||
return m_diagnosis;
|
||||
}
|
||||
|
||||
void CppElementEvaluator::clear()
|
||||
{
|
||||
m_element.clear();
|
||||
m_diagnosis.clear();
|
||||
return d->m_functor.m_diagnosis;
|
||||
}
|
||||
|
||||
Utils::Link CppElementEvaluator::linkFromExpression(const QString &expression, const QString &fileName)
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
#include <QStringList>
|
||||
#include <QTextCursor>
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace CPlusPlus {
|
||||
class LookupItem;
|
||||
class LookupContext;
|
||||
@@ -48,19 +50,18 @@ namespace CppTools {
|
||||
class CppElement;
|
||||
class CppModelManager;
|
||||
|
||||
class CPPTOOLS_EXPORT CppElementEvaluator
|
||||
class CPPTOOLS_EXPORT CppElementEvaluator final
|
||||
{
|
||||
public:
|
||||
explicit CppElementEvaluator(TextEditor::TextEditorWidget *editor);
|
||||
~CppElementEvaluator();
|
||||
|
||||
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();
|
||||
QFuture<QSharedPointer<CppElement>> asyncExecute();
|
||||
QFuture<QSharedPointer<CppElement>> asyncExpressionExecute();
|
||||
static QFuture<QSharedPointer<CppElement>> asyncExecute(TextEditor::TextEditorWidget *editor);
|
||||
static QFuture<QSharedPointer<CppElement>> asyncExecute(const QString &expression,
|
||||
const QString &fileName);
|
||||
bool identifiedCppElement() const;
|
||||
const QSharedPointer<CppElement> &cppElement() const;
|
||||
bool hasDiagnosis() const;
|
||||
@@ -69,41 +70,7 @@ public:
|
||||
static Utils::Link linkFromExpression(const QString &expression, const QString &fileName);
|
||||
|
||||
private:
|
||||
void clear();
|
||||
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 CppElementEvaluatorPrivate *d;
|
||||
};
|
||||
|
||||
class CppClass;
|
||||
|
||||
Reference in New Issue
Block a user