aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs
diff options
context:
space:
mode:
authorNikolai Kosjar <[email protected]>2013-01-10 17:11:03 +0100
committerErik Verbruggen <[email protected]>2013-01-23 14:30:39 +0100
commit8c3794f9d104a39b7f91764b7725dad8726fbde0 (patch)
tree0b370c80468fbf185b99cf9a3f4e452ff171d6b3 /src/libs
parentb6a9d58f690834c7629762a21e520f72a282d2a8 (diff)
C++: Add star binding to TypePrettyPrinter
Now we can specify if we want to print a whitespace before and/or after '*'/'&' when printing pointer and reference types. Task-number: QTCREATORBUG-6169 Change-Id: Ida1b035aa4fd79be9108934b75f236db9f7238af Reviewed-by: Erik Verbruggen <[email protected]>
Diffstat (limited to 'src/libs')
-rw-r--r--src/libs/cplusplus/Overview.cpp9
-rw-r--r--src/libs/cplusplus/Overview.h59
-rw-r--r--src/libs/cplusplus/TypePrettyPrinter.cpp141
-rw-r--r--src/libs/cplusplus/TypePrettyPrinter.h29
4 files changed, 197 insertions, 41 deletions
diff --git a/src/libs/cplusplus/Overview.cpp b/src/libs/cplusplus/Overview.cpp
index 748033d8599..330d2a62dd1 100644
--- a/src/libs/cplusplus/Overview.cpp
+++ b/src/libs/cplusplus/Overview.cpp
@@ -38,14 +38,15 @@
using namespace CPlusPlus;
Overview::Overview()
- : markedArgument(0),
- markedArgumentBegin(0),
- markedArgumentEnd(0),
+ : starBindFlags(BindToIdentifier), // default to "Qt Style"
showArgumentNames(false),
showReturnTypes(false),
showFunctionSignatures(true),
showDefaultArguments(true),
- showTemplateParameters(false)
+ showTemplateParameters(false),
+ markedArgument(0),
+ markedArgumentBegin(0),
+ markedArgumentEnd(0)
{ }
QString Overview::prettyName(const Name *name) const
diff --git a/src/libs/cplusplus/Overview.h b/src/libs/cplusplus/Overview.h
index 344c976f998..339a6d8fc7a 100644
--- a/src/libs/cplusplus/Overview.h
+++ b/src/libs/cplusplus/Overview.h
@@ -37,6 +37,16 @@
namespace CPlusPlus {
+/*!
+ \class Overview
+
+ \brief Converts a FullySpecifiedType and/or any qualified name,
+ to its string representation.
+
+ The public data members (except the ones starting with "marked")
+ determine what exactly and how to print.
+ */
+
class CPLUSPLUS_EXPORT Overview
{
Overview(const Overview &other);
@@ -60,14 +70,57 @@ public:
QString prettyType(const FullySpecifiedType &type, const QString &name) const;
public:
- unsigned markedArgument;
- int markedArgumentBegin;
- int markedArgumentEnd;
+ /*!
+ \enum Overview::StarBindFlag
+
+ The StarBindFlags describe how the '*' and '&' in pointers/references
+ should be bound in the string representation.
+
+ This also applies to rvalue references ('&&'), but not to
+ pointers to functions or arrays like in
+
+ void (*p)()
+ void (*p)[]
+
+ since it seems to be quite uncommon to use spaces there.
+
+ See the examples below. These assume that exactly one
+ flag is set. That is, it may look different with
+ flag combinations.
+
+ \value BindToIdentifier
+ e.g. "char *foo", but not "char * foo"
+ \value BindToTypeName
+ e.g. "char*", but not "char *"
+ \value BindToLeftSpecifier
+ e.g. "char * const* const", but not "char * const * const"
+ \value BindToRightSpecifier
+ e.g. "char *const", but not "char * const"
+ */
+ enum StarBindFlag {
+ BindToIdentifier = 0x1,
+ BindToTypeName = 0x2,
+ BindToLeftSpecifier = 0x4,
+ BindToRightSpecifier = 0x8
+ };
+ Q_DECLARE_FLAGS(StarBindFlags, StarBindFlag)
+
+ StarBindFlags starBindFlags;
bool showArgumentNames: 1;
bool showReturnTypes: 1;
bool showFunctionSignatures: 1;
bool showDefaultArguments: 1;
bool showTemplateParameters: 1;
+
+ /*!
+ You can get the start and end position of a function argument
+ in the resulting string. Set "markedArgument" to the desired
+ argument. After processing, "markedArgumentBegin" and
+ "markedArgumentEnd" will contain the positions.
+ */
+ unsigned markedArgument;
+ int markedArgumentBegin;
+ int markedArgumentEnd;
};
} // namespace CPlusPlus
diff --git a/src/libs/cplusplus/TypePrettyPrinter.cpp b/src/libs/cplusplus/TypePrettyPrinter.cpp
index 8c5bdf51102..84f602337f3 100644
--- a/src/libs/cplusplus/TypePrettyPrinter.cpp
+++ b/src/libs/cplusplus/TypePrettyPrinter.cpp
@@ -44,6 +44,8 @@ using namespace CPlusPlus;
TypePrettyPrinter::TypePrettyPrinter(const Overview *overview)
: _overview(overview)
, _needsParens(false)
+ , _isIndirectionType(false)
+ , _isIndirectionToArrayOrFunction(false)
{ }
TypePrettyPrinter::~TypePrettyPrinter()
@@ -91,13 +93,28 @@ QString TypePrettyPrinter::switchName(const QString &name)
const QString previousName = _name;
_name = name;
return previousName;
+
}
-QString TypePrettyPrinter::switchText(const QString &name)
+bool TypePrettyPrinter::switchIsIndirectionType(bool isIndirectionType)
{
- QString previousName = _text;
- _text = name;
- return previousName;
+ bool previousIsIndirectionType = _isIndirectionType;
+ _isIndirectionType = isIndirectionType;
+ return previousIsIndirectionType;
+}
+
+bool TypePrettyPrinter::switchIsIndirectionToArrayOrFunction(bool isIndirectionToArrayOrFunction)
+{
+ bool previousIsIndirectionToArrayOrFunction = _isIndirectionToArrayOrFunction;
+ _isIndirectionToArrayOrFunction = isIndirectionToArrayOrFunction;
+ return previousIsIndirectionToArrayOrFunction;
+}
+
+QString TypePrettyPrinter::switchText(const QString &text)
+{
+ QString previousText = _text;
+ _text = text;
+ return previousText;
}
bool TypePrettyPrinter::switchNeedsParens(bool needsParens)
@@ -175,6 +192,46 @@ void TypePrettyPrinter::visit(Enum *type)
prependCv(_fullySpecifiedType);
}
+void TypePrettyPrinter::visitIndirectionType(
+ const TypePrettyPrinter::IndirectionType indirectionType,
+ const FullySpecifiedType &elementType,
+ bool isIndirectionToArrayOrFunction)
+{
+ QLatin1Char indirectionSign = indirectionType == aPointerType
+ ? QLatin1Char('*') : QLatin1Char('&');
+
+ const bool prevIsIndirectionType = switchIsIndirectionType(true);
+ const bool hasName = ! _name.isEmpty();
+ if (hasName) {
+ _text.prepend(_name);
+ _name.clear();
+ }
+ prependCv(_fullySpecifiedType);
+
+ if (_text.startsWith(QLatin1Char('&')) && indirectionType != aPointerType)
+ _text.prepend(QLatin1Char(' '));
+
+ const bool prevIsIndirectionToArrayOrFunction
+ = switchIsIndirectionToArrayOrFunction(isIndirectionToArrayOrFunction);
+
+ // Space after indirectionSign?
+ prependSpaceAfterIndirection(hasName);
+
+ // Write indirectionSign or reference
+ if (indirectionType == aRvalueReferenceType)
+ _text.prepend(QLatin1String("&&"));
+ else
+ _text.prepend(indirectionSign);
+
+ // Space before indirectionSign?
+ prependSpaceBeforeIndirection(elementType);
+
+ _needsParens = true;
+ acceptType(elementType);
+ (bool) switchIsIndirectionToArrayOrFunction(prevIsIndirectionToArrayOrFunction);
+ (bool) switchIsIndirectionType(prevIsIndirectionType);
+}
+
void TypePrettyPrinter::visit(IntegerType *type)
{
prependSpaceUnlessBracket();
@@ -246,35 +303,54 @@ void TypePrettyPrinter::visit(PointerToMemberType *type)
acceptType(type->elementType());
}
+void TypePrettyPrinter::prependSpaceBeforeIndirection(const FullySpecifiedType &type)
+{
+ const bool elementTypeIsPointerOrReference = type.type()->isPointerType()
+ || type.type()->isReferenceType();
+ const bool elementIsConstPointerOrReference = elementTypeIsPointerOrReference && type.isConst();
+ const bool shouldBindToLeftSpecifier = _overview->starBindFlags & Overview::BindToLeftSpecifier;
+ if (elementIsConstPointerOrReference && ! shouldBindToLeftSpecifier)
+ _text.prepend(QLatin1String(" "));
+}
+
+void TypePrettyPrinter::prependSpaceAfterIndirection(bool hasName)
+{
+ const bool hasCvSpecifier = _fullySpecifiedType.isConst() || _fullySpecifiedType.isVolatile();
+ const bool shouldBindToIdentifier = _overview->starBindFlags & Overview::BindToIdentifier;
+ const bool shouldBindToRightSpecifier =
+ _overview->starBindFlags & Overview::BindToRightSpecifier;
+
+ const bool spaceBeforeNameNeeded = hasName && ! shouldBindToIdentifier
+ && ! _isIndirectionToArrayOrFunction;
+ const bool spaceBeforeSpecifierNeeded = hasCvSpecifier && ! shouldBindToRightSpecifier;
+
+ const bool case1 = hasCvSpecifier && spaceBeforeSpecifierNeeded;
+ const bool case2 = ! hasCvSpecifier && spaceBeforeNameNeeded;
+ // case 3: In "char *argv[]", put a space between '*' and "argv" when requested
+ const bool case3 = ! hasCvSpecifier && ! shouldBindToIdentifier
+ && ! _isIndirectionToArrayOrFunction && _text.size() && _text.at(0).isLetter();
+ if (case1 || case2 || case3)
+ _text.prepend(QLatin1String(" "));
+}
+
void TypePrettyPrinter::visit(PointerType *type)
{
- if (! _name.isEmpty()) {
- _text.prepend(_name);
- _name.clear();
- }
- prependCv(_fullySpecifiedType);
- _text.prepend(QLatin1String("*"));
- _needsParens = true;
- acceptType(type->elementType());
+ const bool isIndirectionToFunction = type->elementType().type()->isFunctionType();
+ const bool isIndirectionToArray = type->elementType().type()->isArrayType();
+
+ visitIndirectionType(aPointerType, type->elementType(),
+ isIndirectionToFunction || isIndirectionToArray);
}
void TypePrettyPrinter::visit(ReferenceType *type)
{
- if (! _name.isEmpty()) {
- _text.prepend(_name);
- _name.clear();
- }
- prependCv(_fullySpecifiedType);
-
- if (_text.startsWith(QLatin1Char('&')))
- _text.prepend(QLatin1Char(' '));
+ const bool isIndirectionToFunction = type->elementType().type()->isFunctionType();
+ const bool isIndirectionToArray = type->elementType().type()->isArrayType();
+ const IndirectionType indirectionType = type->isRvalueReference()
+ ? aRvalueReferenceType : aReferenceType;
- if (type->isRvalueReference())
- _text.prepend(QLatin1String("&&"));
- else
- _text.prepend(QLatin1String("&"));
- _needsParens = true;
- acceptType(type->elementType());
+ visitIndirectionType(indirectionType, type->elementType(),
+ isIndirectionToFunction || isIndirectionToArray);
}
void TypePrettyPrinter::visit(ArrayType *type)
@@ -326,6 +402,7 @@ void TypePrettyPrinter::visit(Function *type)
if (_overview->showFunctionSignatures) {
Overview argumentText;
+ argumentText.starBindFlags = _overview->starBindFlags;
argumentText.showReturnTypes = true;
argumentText.showArgumentNames = false;
argumentText.showFunctionSignatures = true;
@@ -393,8 +470,16 @@ void TypePrettyPrinter::prependSpaceUnlessBracket()
const QChar ch = _text.at(0);
- if (ch != QLatin1Char('['))
- _text.prepend(QLatin1Char(' '));
+ if (ch != QLatin1Char('[')) {
+ const bool shouldBindToTypeNam = _overview->starBindFlags & Overview::BindToTypeName;
+ const bool caseNoIndirection = ! _isIndirectionType;
+ const bool caseIndirectionToArrayOrFunction = _isIndirectionType
+ && _isIndirectionToArrayOrFunction;
+ const bool casePointerNoBind = _isIndirectionType && ! _isIndirectionToArrayOrFunction
+ && ! shouldBindToTypeNam;
+ if (caseNoIndirection || caseIndirectionToArrayOrFunction || casePointerNoBind)
+ _text.prepend(QLatin1Char(' '));
+ }
}
void TypePrettyPrinter::prependWordSeparatorSpace()
diff --git a/src/libs/cplusplus/TypePrettyPrinter.h b/src/libs/cplusplus/TypePrettyPrinter.h
index ffda3113c14..1628306d0ac 100644
--- a/src/libs/cplusplus/TypePrettyPrinter.h
+++ b/src/libs/cplusplus/TypePrettyPrinter.h
@@ -39,6 +39,14 @@ namespace CPlusPlus {
class Overview;
class FullySpecifiedType;
+/*!
+ \class TypePrettyPrinter
+
+ \brief Helper class for Overview. Does the main type conversation work.
+
+ Don't use this class directly, use Overview instead.
+ */
+
class CPLUSPLUS_EXPORT TypePrettyPrinter: protected TypeVisitor
{
public:
@@ -50,11 +58,7 @@ public:
QString operator()(const FullySpecifiedType &type);
QString operator()(const FullySpecifiedType &type, const QString &name);
-protected:
- QString switchText(const QString &text = QString());
- bool switchNeedsParens(bool needsParens);
- QString switchName(const QString &name);
-
+private:
void acceptType(const FullySpecifiedType &ty);
virtual void visit(UndefinedType *type);
@@ -72,17 +76,30 @@ protected:
virtual void visit(Class *type);
virtual void visit(Enum *type);
+ QString switchName(const QString &name);
+ QString switchText(const QString &text = QString());
+ bool switchNeedsParens(bool needsParens);
+ bool switchIsIndirectionType(bool isIndirectionType);
+ bool switchIsIndirectionToArrayOrFunction(bool isIndirectionToArrayOrFunction);
+
void appendSpace();
void prependSpaceUnlessBracket();
void prependWordSeparatorSpace();
void prependCv(const FullySpecifiedType &ty);
+ void prependSpaceAfterIndirection(bool hasName);
+ void prependSpaceBeforeIndirection(const FullySpecifiedType &type);
+
+ enum IndirectionType { aPointerType, aReferenceType, aRvalueReferenceType };
+ void visitIndirectionType(const IndirectionType indirectionType,
+ const FullySpecifiedType &elementType, bool isIndirectionToArrayOrFunction);
-private:
const Overview *_overview;
QString _name;
QString _text;
FullySpecifiedType _fullySpecifiedType;
bool _needsParens;
+ bool _isIndirectionType;
+ bool _isIndirectionToArrayOrFunction;
};
} // namespace CPlusPlus