aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/cplusplus/TypePrettyPrinter.cpp
diff options
context:
space:
mode:
authorNikolai Kosjar <nikolai.kosjar@digia.com>2013-01-10 17:11:03 +0100
committerErik Verbruggen <erik.verbruggen@digia.com>2013-01-23 14:30:39 +0100
commit8c3794f9d104a39b7f91764b7725dad8726fbde0 (patch)
tree0b370c80468fbf185b99cf9a3f4e452ff171d6b3 /src/libs/cplusplus/TypePrettyPrinter.cpp
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 <erik.verbruggen@digia.com>
Diffstat (limited to 'src/libs/cplusplus/TypePrettyPrinter.cpp')
-rw-r--r--src/libs/cplusplus/TypePrettyPrinter.cpp141
1 files changed, 113 insertions, 28 deletions
diff --git a/src/libs/cplusplus/TypePrettyPrinter.cpp b/src/libs/cplusplus/TypePrettyPrinter.cpp
index 8c5bdf5110..84f602337f 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()