Improved the C++ hover handler.

Done with: bjorn
This commit is contained in:
Roberto Raggi
2009-02-16 17:55:05 +01:00
parent 01145fd552
commit fa216de41c
4 changed files with 164 additions and 48 deletions

View File

@@ -42,7 +42,8 @@ Overview::Overview()
: _markArgument(0), : _markArgument(0),
_showArgumentNames(false), _showArgumentNames(false),
_showReturnTypes(false), _showReturnTypes(false),
_showFunctionSignatures(true) _showFunctionSignatures(true),
_showFullyQualifiedNames(false)
{ } { }
Overview::~Overview() Overview::~Overview()
@@ -88,6 +89,16 @@ void Overview::setShowFunctionSignatures(bool showFunctionSignatures)
_showFunctionSignatures = showFunctionSignatures; _showFunctionSignatures = showFunctionSignatures;
} }
bool Overview::showFullyQualifiedNames() const
{
return _showFullyQualifiedNames;
}
void Overview::setShowFullyQualifiedNamed(bool showFullyQualifiedNames)
{
_showFullyQualifiedNames = showFullyQualifiedNames;
}
QString Overview::prettyName(Name *name) const QString Overview::prettyName(Name *name) const
{ {
NamePrettyPrinter pp(this); NamePrettyPrinter pp(this);

View File

@@ -57,6 +57,9 @@ public:
bool showFunctionSignatures() const; bool showFunctionSignatures() const;
void setShowFunctionSignatures(bool showFunctionSignatures); void setShowFunctionSignatures(bool showFunctionSignatures);
bool showFullyQualifiedNames() const;
void setShowFullyQualifiedNamed(bool showFullyQualifiedNames);
// 1-based // 1-based
// ### rename // ### rename
unsigned markArgument() const; unsigned markArgument() const;
@@ -77,6 +80,7 @@ private:
bool _showArgumentNames: 1; bool _showArgumentNames: 1;
bool _showReturnTypes: 1; bool _showReturnTypes: 1;
bool _showFunctionSignatures: 1; bool _showFunctionSignatures: 1;
bool _showFullyQualifiedNames: 1;
}; };
} // end of namespace CPlusPlus } // end of namespace CPlusPlus

View File

@@ -37,9 +37,41 @@
#include <CoreTypes.h> #include <CoreTypes.h>
#include <Symbols.h> #include <Symbols.h>
#include <Scope.h> #include <Scope.h>
#include <QStringList>
#include <QtDebug>
using namespace CPlusPlus; using namespace CPlusPlus;
static QString fullyQualifiedName(Symbol *symbol, const Overview *overview)
{
QStringList nestedNameSpecifier;
for (Scope *scope = symbol->scope(); scope && scope->enclosingScope();
scope = scope->enclosingScope())
{
Symbol *owner = scope->owner();
if (! owner) {
qWarning() << "invalid scope."; // ### better message.
continue;
}
if (! owner->name())
nestedNameSpecifier.prepend(QLatin1String("<anonymous>"));
else {
const QString name = overview->prettyName(owner->name());
nestedNameSpecifier.prepend(name);
}
}
nestedNameSpecifier.append(overview->prettyName(symbol->name()));
return nestedNameSpecifier.join(QLatin1String("::"));
}
TypePrettyPrinter::TypePrettyPrinter(const Overview *overview) TypePrettyPrinter::TypePrettyPrinter(const Overview *overview)
: _overview(overview), : _overview(overview),
_name(0) _name(0)
@@ -150,16 +182,26 @@ void TypePrettyPrinter::visit(Namespace *type)
applyPtrOperators(); applyPtrOperators();
} }
void TypePrettyPrinter::visit(Class *type) void TypePrettyPrinter::visit(Class *classTy)
{ {
_text += overview()->prettyName(type->name()); if (overview()->showFullyQualifiedNames())
_text += fullyQualifiedName(classTy, overview());
else
_text += overview()->prettyName(classTy->name());
applyPtrOperators(); applyPtrOperators();
} }
void TypePrettyPrinter::visit(Enum *type) void TypePrettyPrinter::visit(Enum *type)
{ {
_text += overview()->prettyName(type->name()); if (overview()->showFullyQualifiedNames())
_text += fullyQualifiedName(type, overview());
else
_text += overview()->prettyName(type->name());
applyPtrOperators(); applyPtrOperators();
} }
@@ -259,11 +301,14 @@ void TypePrettyPrinter::visit(Function *type)
if (! _ptrOperators.isEmpty()) { if (! _ptrOperators.isEmpty()) {
out(QLatin1Char('(')); out(QLatin1Char('('));
applyPtrOperators(false); applyPtrOperators(false);
if (! _name.isEmpty()) { if (! _name.isEmpty()) {
_text += _name; _text += _name;
_name.clear(); _name.clear();
} }
out(QLatin1Char(')')); out(QLatin1Char(')'));
} else if (! _name.isEmpty() && _overview->showFunctionSignatures()) { } else if (! _name.isEmpty() && _overview->showFunctionSignatures()) {
space(); space();
out(_name); out(_name);

View File

@@ -47,6 +47,7 @@
#include <CoreTypes.h> #include <CoreTypes.h>
#include <FullySpecifiedType.h> #include <FullySpecifiedType.h>
#include <Literals.h> #include <Literals.h>
#include <Control.h>
#include <Names.h> #include <Names.h>
#include <Scope.h> #include <Scope.h>
#include <Symbol.h> #include <Symbol.h>
@@ -141,33 +142,13 @@ void CppHoverHandler::showToolTip(TextEditor::ITextEditor *editor, const QPoint
} }
} }
static QString buildHelpId(const FullySpecifiedType &type, static QString buildHelpId(Symbol *symbol, Name *name)
const Symbol *symbol)
{ {
Name *name = 0;
Scope *scope = 0; Scope *scope = 0;
if (const Function *f = type->asFunctionType()) { if (symbol) {
name = f->name(); scope = symbol->scope();
scope = f->scope(); name = symbol->name();
} else if (const Class *c = type->asClassType()) {
name = c->name();
scope = c->scope();
} else if (const Enum *e = type->asEnumType()) {
name = e->name();
scope = e->scope();
} else if (const ForwardClassDeclaration *fwd = type->asForwardClassDeclarationType()) {
name = fwd->name();
scope = fwd->scope();
} else if (const NamedType *t = type->asNamedType()) {
name = t->name();
} else if (symbol && symbol->isDeclaration()) {
const Declaration *d = symbol->asDeclaration();
if (d->scope() && d->scope()->isEnumScope()) {
name = d->name();
scope = d->scope();
}
} }
if (! name) if (! name)
@@ -185,14 +166,13 @@ static QString buildHelpId(const FullySpecifiedType &type,
if (owner && owner->name() && ! scope->isEnumScope()) { if (owner && owner->name() && ! scope->isEnumScope()) {
Name *name = owner->name(); Name *name = owner->name();
Identifier *id = 0; Identifier *id = 0;
if (NameId *nameId = name->asNameId()) { if (NameId *nameId = name->asNameId())
id = nameId->identifier(); id = nameId->identifier();
} else if (TemplateNameId *nameId = name->asTemplateNameId()) {
else if (TemplateNameId *nameId = name->asTemplateNameId())
id = nameId->identifier(); id = nameId->identifier();
}
if (id) if (id)
qualifiedNames.prepend(QString::fromLatin1(id->chars(), id->size())); qualifiedNames.prepend(QString::fromLatin1(id->chars(), id->size()));
@@ -202,6 +182,70 @@ static QString buildHelpId(const FullySpecifiedType &type,
return qualifiedNames.join(QLatin1String("::")); return qualifiedNames.join(QLatin1String("::"));
} }
// ### move me
static FullySpecifiedType resolve(const FullySpecifiedType &ty,
const LookupContext &context,
Symbol **resolvedSymbol,
Name **resolvedName)
{
Control *control = context.control();
if (const PointerType *ptrTy = ty->asPointerType()) {
return control->pointerType(resolve(ptrTy->elementType(), context,
resolvedSymbol, resolvedName));
} else if (const ReferenceType *refTy = ty->asReferenceType()) {
return control->referenceType(resolve(refTy->elementType(), context,
resolvedSymbol, resolvedName));
} else if (const PointerToMemberType *ptrToMemTy = ty->asPointerToMemberType()) {
return control->pointerToMemberType(ptrToMemTy->memberName(),
resolve(ptrToMemTy->elementType(), context,
resolvedSymbol, resolvedName));
} else if (const NamedType *namedTy = ty->asNamedType()) {
if (resolvedName)
*resolvedName = namedTy->name();
const QList<Symbol *> candidates = context.resolve(namedTy->name());
foreach (Symbol *c, candidates) {
if (c->isClass() || c->isEnum()) {
if (resolvedSymbol)
*resolvedSymbol = c;
return c->type();
}
}
} else if (const Namespace *nsTy = ty->asNamespaceType()) {
if (resolvedName)
*resolvedName = nsTy->name();
} else if (const Class *classTy = ty->asClassType()) {
if (resolvedName)
*resolvedName = classTy->name();
if (resolvedSymbol)
*resolvedSymbol = const_cast<Class *>(classTy);
} else if (const ForwardClassDeclaration *fwdClassTy = ty->asForwardClassDeclarationType()) {
if (resolvedName)
*resolvedName = fwdClassTy->name();
} else if (const Enum *enumTy = ty->asEnumType()) {
if (resolvedName)
*resolvedName = enumTy->name();
} else if (const Function *funTy = ty->asFunctionType()) {
if (resolvedName)
*resolvedName = funTy->name();
}
return ty;
}
void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, int pos) void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, int pos)
{ {
m_helpId.clear(); m_helpId.clear();
@@ -270,26 +314,38 @@ void CppHoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, in
typeOfExpression(expression, doc, lastSymbol); typeOfExpression(expression, doc, lastSymbol);
if (!types.isEmpty()) { if (!types.isEmpty()) {
FullySpecifiedType firstType = types.first().first; const TypeOfExpression::Result result = types.first();
Symbol *symbol = types.first().second;
FullySpecifiedType docType = firstType;
if (const PointerType *pt = firstType->asPointerType()) { FullySpecifiedType firstType = result.first; // result of `type of expression'.
docType = pt->elementType(); Symbol *lookupSymbol = result.second; // lookup symbol
} else if (const ReferenceType *rt = firstType->asReferenceType()) {
docType = rt->elementType();
}
m_helpId = buildHelpId(docType, symbol); Symbol *resolvedSymbol = 0;
QString displayName = buildHelpId(firstType, symbol); Name *resolvedName = 0;
firstType = resolve(firstType, typeOfExpression.lookupContext(),
&resolvedSymbol, &resolvedName);
if (!firstType->isClassType() && !firstType->isNamedType()) { m_helpId = buildHelpId(resolvedSymbol, resolvedName);
Overview overview;
overview.setShowArgumentNames(true); Symbol *symbol = result.second;
overview.setShowReturnTypes(true); if (resolvedSymbol)
m_toolTip = overview.prettyType(firstType, displayName); symbol = resolvedSymbol;
} else {
Overview overview;
overview.setShowArgumentNames(true);
overview.setShowReturnTypes(true);
overview.setShowFullyQualifiedNamed(true);
if (lookupSymbol && lookupSymbol->isDeclaration()) {
Declaration *decl = lookupSymbol->asDeclaration();
m_toolTip = overview.prettyType(firstType, decl->name());
} else if (firstType->isClassType() || firstType->isEnumType() ||
firstType->isForwardClassDeclarationType()) {
m_toolTip = m_helpId; m_toolTip = m_helpId;
} else {
m_toolTip = overview.prettyType(firstType, m_helpId);
} }
} }
} }