m_parenthLevelStack(),
m_logicalLine(),
m_continued(false),
- m_lastDeclToken(-1),
m_writer(NULL),
m_logger(logger),
m_tabSize(4),
m_useTab(true),
m_lexer(NULL),
- m_parser(NULL)
+ m_parser(NULL),
+ m_countIsTypeList(1024),
+ m_isInTypeList(new bool[m_countIsTypeList])
{
}
m_logicalLine.push_back(FormatToken(token, m_parenthLevel));
}
+/**
+ * Find tokens belonging to a type list: cast expressions.
+ *
+ * The position of the tokens will be marked in a boolean array.
+ */
+void CFormatter::findTypeLists()
+{
+ const FormatToken* item2;
+ // search for cast expressions with '*' and/or '&' and/or "[]":
+ // examples: (char&) (int[]) (int* const)
+ int count = m_logicalLine.size();
+ for (int ix = count - 1; ix > 0; ix--){
+ const FormatToken& item = m_logicalLine.constData()[ix];
+ // at least 3 elements: '(' "int" '*'
+ if (item.isOperator(OP_RPARENTH) && ix >= 3){
+ if ( (item2 = &m_logicalLine.constData()[ix - 1])->isOperator(OP_STAR, OP_BIT_AND)
+ || item2->isKeyword(K_CONST) || (item2->isOperator(OP_RBRACKET)
+ && m_logicalLine.constData()[ix - 2].isOperator(OP_LBRACKET))){
+ // mark all tokens until the previous '(' as "in typelist":
+ while(ix > 0 && ! m_logicalLine.constData()[ix].isOperator(OP_LPARENTH))
+ m_isInTypeList[ix--] = true;
+ }
+ }
+ }
+ // search for new expressions:
+ // examples: new String; new Type*[3]; new Type(1, 2);
+ for (int ix = 0; ix < count; ix++){
+ const FormatToken& item = m_logicalLine.constData()[ix];
+ if (item.isKeyword(K_NEW)){
+ while(++ix < count && ((item2 = &m_logicalLine.constData()[ix])
+ ->isOperator(OP_LBRACKET, OP_LPARENTH)
+ || item2->isOperator(OP_SEMICOLON, OP_COMMA)))
+ m_isInTypeList[ix] = true;
+ }
+ }
+ // search for template expressions: '<' types '>':
+ // examples: new QList<abc>
+ for (int ix = 0; ix < count; ix++){
+ const FormatToken& item = m_logicalLine.constData()[ix];
+ if (item.isOperator(OP_LT)){
+ bool found = false;
+ for (int ix2 = ix + 1; ix2 < count; ix2++){
+ item2 = &m_logicalLine.constData()[ix2];
+ if (item2->isOperator(OP_AND, OP_OR))
+ break;
+ if (item2->isOperator(OP_GT)){
+ found = true;
+ break;
+ }
+ if (found){
+ while(++ix < ix2)
+ m_isInTypeList[ix] = true;
+ ix++;
+ }
+ }
+ }
+ }
+}
+
/**
* Write the current locical line to the output media.
*
*/
void CFormatter::flush(bool isPart)
{
+ resetIsTypeList();
+ findTypeLists();
if (m_logicalLine.size() > 0){
QByteArray buffer;
buffer.reserve(8096);
indent(m_blockLevel + m_continued ? 1 : 0, buffer);
FormatToken* lastItem = &m_logicalLine.data()[0];
- buffer.append(lastItem->toString());
+ m_lexer->textOfToken(lastItem, buffer);
for (int ix = 1; ix < m_logicalLine.size(); ix++){
FormatToken* item = &m_logicalLine.data()[ix];
- if (needsBlank(lastItem, item, ix <= m_lastDeclToken))
+ if (needsBlank(lastItem, item, m_isInTypeList[ix]))
buffer.append(' ');
m_lexer->textOfToken(item, buffer);
lastItem = item;
if (! isDeclaration)
rc = needsPrecedingBlank((CppOperator) second->id());
else {
- rc = (op = (CppOperator) second->id()) != OP_STAR
- && op != OP_BIT_AND && op != OP_GT && op != OP_LT;
+ rc = !((op = (CppOperator) second->id()) == OP_STAR
+ || op == OP_BIT_AND || op == OP_GT || op == OP_LT);
}
break;
default:
case TOKEN_REAL:
case TOKEN_KEYWORD:
case TOKEN_ID:
- rc = needsTrailingBlank((CppOperator) first->id());
+ if ( (op = (CppOperator) first->id()) == OP_RPARENTH)
+ rc = true;
+ else
+ rc = needsTrailingBlank((CppOperator) first->id());
break;
case TOKEN_OPERATOR:
if (! isDeclaration)
rc = needsTrailingBlank((CppOperator) first->id())
|| needsPrecedingBlank((CppOperator) second->id());
else {
- rc = (op = (CppOperator) second->id()) != OP_GT && op != OP_LT;
+ rc = false;
}
break;
default:
return rc;
}
+/**
+ * Resets the array storing the indexes of tokens belonging to a declaration.
+ *
+ * Cast expressions also are treated as declarations.
+ *
+ * @return
+ */
+void CFormatter::resetIsTypeList()
+{
+ if (m_countIsTypeList < m_logicalLine.size()){
+ delete[] m_isInTypeList;
+ m_countIsTypeList = max(m_logicalLine.size(), 2 * m_countIsTypeList);
+ m_isInTypeList = new bool[m_countIsTypeList];
+ }
+ memset(m_isInTypeList, false, sizeof *m_isInTypeList * m_countIsTypeList);
+}
+
/**
* Tests whether an operator needs a preceding blank.
*
bool CFormatter::needsPrecedingBlank(CppOperator op)
{
- bool rc = true;
+ bool rc = false;
switch(op){
case OP_QUESTIONMARK:
case OP_COLON:
bool CFormatter::needsTrailingBlank(CppOperator op)
{
- bool rc = true;
+ bool rc = false;
switch(op){
case OP_COMMA:
case OP_QUESTIONMARK:
case OP_DIV:
case OP_MOD:
case OP_NOT:
+ rc = true;
default:
break;
}
*/
void CFormatter::setLastDeclToken(int lastDeclToken)
{
- m_lastDeclToken = lastDeclToken;
+ int count = min(lastDeclToken, m_countIsTypeList);
+ if (count > 0)
+ memset(m_isInTypeList, ~false, count * sizeof *m_isInTypeList);
}
/**
{
return m_writer;
}
+