Merge pull request #2 from steinwurf/fix-formatting

Fix formatting
This commit is contained in:
Peter Vingelmann 2016-09-16 22:42:05 +02:00 committed by GitHub
commit 4e8f6c8745
5 changed files with 280 additions and 121 deletions

View File

@ -180,6 +180,7 @@ ASBeautifier::ASBeautifier(const ASBeautifier& other) : ASBase(other)
isInStatement = other.isInStatement; isInStatement = other.isInStatement;
isInHeader = other.isInHeader; isInHeader = other.isInHeader;
isInTemplate = other.isInTemplate; isInTemplate = other.isInTemplate;
isInTemplateInstantiation = other.isInTemplateInstantiation;
isInDefine = other.isInDefine; isInDefine = other.isInDefine;
isInDefineDefinition = other.isInDefineDefinition; isInDefineDefinition = other.isInDefineDefinition;
classIndent = other.classIndent; classIndent = other.classIndent;
@ -226,6 +227,7 @@ ASBeautifier::ASBeautifier(const ASBeautifier& other) : ASBase(other)
shouldAlignMethodColon = other.shouldAlignMethodColon; shouldAlignMethodColon = other.shouldAlignMethodColon;
shouldIndentPreprocDefine = other.shouldIndentPreprocDefine; shouldIndentPreprocDefine = other.shouldIndentPreprocDefine;
shouldIndentPreprocConditional = other.shouldIndentPreprocConditional; shouldIndentPreprocConditional = other.shouldIndentPreprocConditional;
potentialTemplateDisambiguator = other.potentialTemplateDisambiguator;
indentCount = other.indentCount; indentCount = other.indentCount;
spaceIndentCount = other.spaceIndentCount; spaceIndentCount = other.spaceIndentCount;
spaceIndentObjCMethodDefinition = other.spaceIndentObjCMethodDefinition; spaceIndentObjCMethodDefinition = other.spaceIndentObjCMethodDefinition;
@ -252,6 +254,7 @@ ASBeautifier::ASBeautifier(const ASBeautifier& other) : ASBase(other)
currentNonSpaceCh = other.currentNonSpaceCh; currentNonSpaceCh = other.currentNonSpaceCh;
currentNonLegalCh = other.currentNonLegalCh; currentNonLegalCh = other.currentNonLegalCh;
prevNonLegalCh = other.prevNonLegalCh; prevNonLegalCh = other.prevNonLegalCh;
lineFirstChar = other.lineFirstChar;
} }
/** /**
@ -344,7 +347,9 @@ void ASBeautifier::init(ASSourceIterator* iter)
isInLet = false; isInLet = false;
isInHeader = false; isInHeader = false;
isInTemplate = false; isInTemplate = false;
isInTemplateInstantiation = false;
isInConditional = false; isInConditional = false;
potentialTemplateDisambiguator = false;
indentCount = 0; indentCount = 0;
spaceIndentCount = 0; spaceIndentCount = 0;
@ -365,6 +370,7 @@ void ASBeautifier::init(ASSourceIterator* iter)
prevNonLegalCh = '{'; prevNonLegalCh = '{';
currentNonLegalCh = '{'; currentNonLegalCh = '{';
quoteChar = ' '; quoteChar = ' ';
lineFirstChar = ' ';
probationHeader = NULL; probationHeader = NULL;
lastLineHeader = NULL; lastLineHeader = NULL;
backslashEndsPrevLine = false; backslashEndsPrevLine = false;
@ -879,6 +885,7 @@ string ASBeautifier::beautify(const string& originalLine)
haveLineContinuationChar = false; haveLineContinuationChar = false;
lineOpeningBlocksNum = 0; lineOpeningBlocksNum = 0;
lineClosingBlocksNum = 0; lineClosingBlocksNum = 0;
lineFirstChar = ' ';
if (isImmediatelyPostObjCMethodDefinition) if (isImmediatelyPostObjCMethodDefinition)
clearObjCMethodDefinitionAlignment(); clearObjCMethodDefinitionAlignment();
@ -920,6 +927,7 @@ string ASBeautifier::beautify(const string& originalLine)
line = trim(originalLine); line = trim(originalLine);
if (line.length() > 0) if (line.length() > 0)
{ {
lineFirstChar = line[0];
if (line[0] == '{') if (line[0] == '{')
lineBeginsWithOpenBracket = true; lineBeginsWithOpenBracket = true;
else if (line[0] == '}') else if (line[0] == '}')
@ -1253,10 +1261,12 @@ void ASBeautifier::registerInStatementIndent(const string& line, int i, int spac
int tabIncrementIn, int minIndent, bool updateParenStack) int tabIncrementIn, int minIndent, bool updateParenStack)
{ {
int remainingCharNum = line.length() - i; int remainingCharNum = line.length() - i;
int nextNonWSChar = getNextProgramCharDistance(line, i); // Get the next program char distance to determine if the remaining
// text is comment-only
int nextProgramChar = getNextProgramCharDistance(line, i);
// if indent is around the last char in the line, indent instead one indent from the previous indent // if indent is around the last char in the line, indent instead one indent from the previous indent
if (nextNonWSChar == remainingCharNum) if (nextProgramChar == remainingCharNum)
{ {
int previousIndent = spaceTabCount_; int previousIndent = spaceTabCount_;
if (!inStatementIndentStack->empty()) if (!inStatementIndentStack->empty())
@ -1271,6 +1281,13 @@ void ASBeautifier::registerInStatementIndent(const string& line, int i, int spac
return; return;
} }
// The next line should be aligned with the next non-whitespace character.
// This character could be a beginning of a comment
int nextNonWSChar = 1;
size_t nextCharPos = line.find_first_not_of(" \t", i + 1);
if (nextCharPos != string::npos)
nextNonWSChar = nextCharPos - i;
if (updateParenStack) if (updateParenStack)
parenIndentStack->push_back(i + spaceTabCount_ - horstmannIndentInStatement); parenIndentStack->push_back(i + spaceTabCount_ - horstmannIndentInStatement);
@ -2097,27 +2114,34 @@ void ASBeautifier::computePreliminaryIndentation()
++indentCount; ++indentCount;
isInSwitch = true; isInSwitch = true;
} }
} // end of for loop } // end of for loop
if (isInClassHeader) if (isInClassHeader)
{ {
if (!isJavaStyle()) if (!isJavaStyle())
isInClassHeaderTab = true; isInClassHeaderTab = true;
if (lineOpensWithLineComment || lineStartsInComment || lineOpensWithComment) if (blockIndent)
{
if (!lineBeginsWithOpenBracket)
--indentCount;
if (!inStatementIndentStack->empty())
spaceIndentCount -= inStatementIndentStack->back();
}
else if (blockIndent)
{ {
if (!lineBeginsWithOpenBracket) if (!lineBeginsWithOpenBracket)
++indentCount; ++indentCount;
} }
} }
if (isInTemplate || isInTemplateInstantiation)
{
// Use symmetrical layout for closing brace in template argument list:
//
// template
// <
// class Argument
// >
if (lineFirstChar == '>' && !lineStartsInComment)
{
if (!inStatementIndentStack->empty())
spaceIndentCount -= inStatementIndentStack->back();
}
}
if (isInClassInitializer || isInEnumTypeID) if (isInClassInitializer || isInEnumTypeID)
{ {
indentCount += classInitializerIndents; indentCount += classInitializerIndents;
@ -2334,7 +2358,6 @@ void ASBeautifier::parseCurrentLine(const string& line)
bool isInOperator = false; bool isInOperator = false;
bool isSpecialChar = false; bool isSpecialChar = false;
bool haveCaseIndent = false; bool haveCaseIndent = false;
bool haveAssignmentThisLine = false;
bool closingBracketReached = false; bool closingBracketReached = false;
bool previousLineProbation = (probationHeader != NULL); bool previousLineProbation = (probationHeader != NULL);
char ch = ' '; char ch = ' ';
@ -2549,6 +2572,14 @@ void ASBeautifier::parseCurrentLine(const string& line)
probationHeader = NULL; probationHeader = NULL;
} }
if (potentialTemplateDisambiguator)
{
// Disable the template disambiguator flag if the next word
// is not "template"
if (ch != 't' || getNextWord(line, i - 1) != AS_TEMPLATE)
potentialTemplateDisambiguator = false;
}
prevNonSpaceCh = currentNonSpaceCh; prevNonSpaceCh = currentNonSpaceCh;
currentNonSpaceCh = ch; currentNonSpaceCh = ch;
if (!isLegalNameChar(ch) && ch != ',' && ch != ';') if (!isLegalNameChar(ch) && ch != ',' && ch != ';')
@ -2565,27 +2596,66 @@ void ASBeautifier::parseCurrentLine(const string& line)
else else
currentHeader = NULL; currentHeader = NULL;
if (isCStyle() && isInTemplate if (isCStyle()
&& (ch == '<' || ch == '>') && (ch == '<' || ch == '>')
&& !(line.length() > i + 1 && line.compare(i, 2, ">=") == 0)) && !(line.length() > i + 1 && line.compare(i, 2, ">=") == 0))
{ {
if (ch == '<') if (isInTemplate)
{ {
++templateDepth; if (ch == '<')
inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size()); {
registerInStatementIndent(line, i, spaceIndentCount, tabIncrementIn, 0, true); ++templateDepth;
} inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
else if (ch == '>') registerInStatementIndent(line, i, spaceIndentCount, tabIncrementIn, 0, true);
{ }
popLastInStatementIndent(); else if (ch == '>')
if (--templateDepth <= 0) {
{ popLastInStatementIndent();
ch = ';'; if (--templateDepth <= 0)
isInTemplate = false; {
templateDepth = 0; ch = ';';
} isInTemplate = false;
} templateDepth = 0;
} }
}
}
else if (parenDepth == 0 && !isInClassHeader)
{
// A template instantiation cannot start with <<
if (ch == '<'
&& !(line.length() > i + 1 && line.compare(i, 2, "<<") == 0))
{
if (!isInStatement && templateDepth == 0)
{
isInTemplateInstantiation = true;
}
++templateDepth;
if (isInTemplateInstantiation)
{
inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
registerInStatementIndent(line, i, spaceIndentCount, tabIncrementIn, 0, true);
isInStatement = true;
}
}
else if (ch == '>' && templateDepth > 0)
{
if (isInTemplateInstantiation
&& !inStatementIndentStackSizeStack->empty())
{
popLastInStatementIndent();
}
if (--templateDepth <= 0)
{
isInTemplateInstantiation = false;
templateDepth = 0;
}
}
}
}
// handle parentheses // handle parentheses
if (ch == '(' || ch == '[' || ch == ')' || ch == ']') if (ch == '(' || ch == '[' || ch == ')' || ch == ']')
@ -2775,7 +2845,13 @@ void ASBeautifier::parseCurrentLine(const string& line)
if (lineBeginsWithOpenBracket || lineBeginsWithComma) if (lineBeginsWithOpenBracket || lineBeginsWithComma)
spaceIndentCount = 0; spaceIndentCount = 0;
} }
else // Do not zero the spaceIndentCount for the current line
// if we are within a statement. This is useful for lambda
// expressions in multiline statements:
//
// std::generate(data.begin(), data.end(),
// [&]() { return randval(engine); });
else if (!isInStatement || lineBeginsWithOpenBracket)
spaceIndentCount = 0; spaceIndentCount = 0;
} }
@ -2819,6 +2895,18 @@ void ASBeautifier::parseCurrentLine(const string& line)
&& ASBeautifier::peekNextChar(line, i + (*newHeader).length() - 1) != '(') && ASBeautifier::peekNextChar(line, i + (*newHeader).length() - 1) != '(')
newHeader = NULL; newHeader = NULL;
// The "template" disambiguator for dependent names should not
// be recognized as an actual template header. For example:
// T::template foo<X>()
// s.template foo<X>();
// this->template foo<X>();
if (isCStyle() && newHeader == &AS_TEMPLATE
&& (potentialTemplateDisambiguator || prevNonSpaceCh == '.'))
{
newHeader = NULL;
potentialTemplateDisambiguator = false;
}
if (newHeader != NULL) if (newHeader != NULL)
{ {
// if we reached here, then this is a header... // if we reached here, then this is a header...
@ -2979,7 +3067,6 @@ void ASBeautifier::parseCurrentLine(const string& line)
if (isSharpStyle() && findKeyword(line, i, AS_LET)) if (isSharpStyle() && findKeyword(line, i, AS_LET))
isInLet = true; isInLet = true;
} // isPotentialHeader } // isPotentialHeader
if (ch == '?') if (ch == '?')
@ -2991,6 +3078,9 @@ void ASBeautifier::parseCurrentLine(const string& line)
if (line.length() > i + 1 && line[i + 1] == ':') // look for :: if (line.length() > i + 1 && line[i + 1] == ':') // look for ::
{ {
++i; ++i;
// The next word might be a template disambiguator like
// T::template foo<X>()
potentialTemplateDisambiguator = true;
continue; continue;
} }
else if (isInQuestion) else if (isInQuestion)
@ -3075,10 +3165,13 @@ void ASBeautifier::parseCurrentLine(const string& line)
} }
if ((ch == ';' || (parenDepth > 0 && ch == ',')) && !inStatementIndentStackSizeStack->empty()) if ((ch == ';' || (parenDepth > 0 && ch == ',')) && !inStatementIndentStackSizeStack->empty())
while ((int) inStatementIndentStackSizeStack->back() + (parenDepth > 0 ? 1 : 0) {
while ((int) inStatementIndentStackSizeStack->back() + (parenDepth > 0 ? 1 : 0)
< (int) inStatementIndentStack->size()) < (int) inStatementIndentStack->size())
{
inStatementIndentStack->pop_back(); inStatementIndentStack->pop_back();
}
}
else if (ch == ',' && isInEnum && isNonInStatementArray && !inStatementIndentStack->empty()) else if (ch == ',' && isInEnum && isNonInStatementArray && !inStatementIndentStack->empty())
inStatementIndentStack->pop_back(); inStatementIndentStack->pop_back();
@ -3103,7 +3196,8 @@ void ASBeautifier::parseCurrentLine(const string& line)
// do nothing for now // do nothing for now
} }
// register indent at second word on the line // register indent at second word on the line
else if (!isInTemplate && !isInClassHeaderTab && !isInClassInitializer) else if (!isInTemplate && !isInClassHeaderTab && !isInClassInitializer
&& !isInClassHeader)
{ {
int prevWord = getInStatementIndentComma(line, i); int prevWord = getInStatementIndentComma(line, i);
int inStatementIndent = prevWord + spaceIndentCount + tabIncrementIn; int inStatementIndent = prevWord + spaceIndentCount + tabIncrementIn;
@ -3223,7 +3317,17 @@ void ASBeautifier::parseCurrentLine(const string& line)
} }
if (parenDepth == 0 && ch == ';') if (parenDepth == 0 && ch == ';')
{
isInStatement = false; isInStatement = false;
isInTemplateInstantiation = false;
templateDepth = 0;
// This is the end of a statement, so the inStatementIndentStack
// should be reset to its default state
while (inStatementIndentStackSizeStack->size() > 1)
inStatementIndentStackSizeStack->pop_back();
inStatementIndentStack->clear();
}
if (isInObjCMethodDefinition) if (isInObjCMethodDefinition)
isImmediatelyPostObjCMethodDefinition = true; isImmediatelyPostObjCMethodDefinition = true;
@ -3400,7 +3504,8 @@ void ASBeautifier::parseCurrentLine(const string& line)
if (foundNonAssignmentOp == &AS_LAMBDA) if (foundNonAssignmentOp == &AS_LAMBDA)
foundPreCommandHeader = true; foundPreCommandHeader = true;
if (isInTemplate && foundNonAssignmentOp == &AS_GR_GR) if ((isInTemplate || isInTemplateInstantiation)
&& foundNonAssignmentOp == &AS_GR_GR)
foundNonAssignmentOp = NULL; foundNonAssignmentOp = NULL;
// Since findHeader's boundary checking was not used above, it is possible // Since findHeader's boundary checking was not used above, it is possible
@ -3420,10 +3525,18 @@ void ASBeautifier::parseCurrentLine(const string& line)
if (foundNonAssignmentOp->length() > 1) if (foundNonAssignmentOp->length() > 1)
i += foundNonAssignmentOp->length() - 1; i += foundNonAssignmentOp->length() - 1;
// The "template" disambiguator for dependent names should not
// be recognized as an actual template header. For example:
// this->template foo<X>();
if (isCStyle() && foundNonAssignmentOp == &AS_ARROW)
{
potentialTemplateDisambiguator = true;
}
// For C++ input/output, operator<< and >> should be // For C++ input/output, operator<< and >> should be
// aligned, if we are not in a statement already and // aligned, if we are not in a statement already and
// also not in the "operator<<(...)" header line // also not in the "operator<<(...)" header line
if (!isInOperator if (!isInOperator && !isInClassHeader
&& inStatementIndentStack->empty() && inStatementIndentStack->empty()
&& isCStyle() && isCStyle()
&& (foundNonAssignmentOp == &AS_GR_GR && (foundNonAssignmentOp == &AS_GR_GR
@ -3447,23 +3560,8 @@ void ASBeautifier::parseCurrentLine(const string& line)
if (!isInOperator && !isInTemplate && (!isNonInStatementArray || isInEnum)) if (!isInOperator && !isInTemplate && (!isNonInStatementArray || isInEnum))
{ {
// if multiple assignments, align on the previous word
if (foundAssignmentOp == &AS_ASSIGN
&& prevNonSpaceCh != ']' // an array
&& statementEndsWithComma(line, i))
{
if (!haveAssignmentThisLine) // only one assignment indent per line
{
// register indent at previous word
haveAssignmentThisLine = true;
int prevWordIndex = getInStatementIndentAssign(line, i);
int inStatementIndent = prevWordIndex + spaceIndentCount + tabIncrementIn;
inStatementIndentStack->push_back(inStatementIndent);
isInStatement = true;
}
}
// don't indent an assignment if 'let' // don't indent an assignment if 'let'
else if (isInLet) if (isInLet)
{ {
isInLet = false; isInLet = false;
} }
@ -3479,5 +3577,4 @@ void ASBeautifier::parseCurrentLine(const string& line)
} }
} // end of for loop * end of for loop * end of for loop * end of for loop * end of for loop * } // end of for loop * end of for loop * end of for loop * end of for loop * end of for loop *
} }
} // end namespace astyle } // end namespace astyle

View File

@ -1209,6 +1209,64 @@ string ASFormatter::nextLine()
} }
} // (isPotentialHeader && !isInTemplate) } // (isPotentialHeader && !isInTemplate)
if (currentChar == ':'
&& previousChar != ':' // not part of '::'
&& peekNextChar() != ':') // not part of '::'
{
if (isInCase)
{
isInCase = false;
if (shouldBreakOneLineStatements)
passedColon = true;
}
else if (isCStyle() // for C/C++ only
&& isOkToBreakBlock(bracketTypeStack->back())
&& shouldBreakOneLineStatements
&& !foundQuestionMark // not in a ?: sequence
&& !foundPreDefinitionHeader // not in a definition block (e.g. class foo : public bar
&& previousCommandChar != ')' // not immediately after closing paren of a method header, e.g. ASFormatter::ASFormatter(...) : ASBeautifier(...)
&& !foundPreCommandHeader // not after a 'noexcept'
&& !squareBracketCount // not in objC method call
&& !isInObjCMethodDefinition // not objC '-' or '+' method
&& !isInObjCInterface // not objC @interface
&& !isInObjCSelector // not objC @selector
&& !isDigit(peekNextChar()) // not a bit field
&& !isInEnum // not an enum with a base type
&& !isInAsm // not in extended assembler
&& !isInAsmOneLine // not in extended assembler
&& !isInAsmBlock) // not in extended assembler
{
passedColon = true;
}
if (isCStyle()
&& shouldPadMethodColon
&& (squareBracketCount > 0 || isInObjCMethodDefinition || isInObjCSelector)
&& !foundQuestionMark) // not in a ?: sequence
padObjCMethodColon();
if (isInObjCInterface)
{
appendSpacePad();
if ((int) currentLine.length() > charNum + 1 && !isWhiteSpace(currentLine[charNum + 1]))
currentLine.insert(charNum + 1, " ");
}
if (isClassInitializer())
{
isInClassInitializer = true;
if (!isCharImmediatelyPostComment && !isCharImmediatelyPostLineComment)
{
// Attach colon to the constructor header and force a
// new line before the member initializer list
appendSpacePad();
appendCurrentChar(false);
shouldBreakLineAtNextChar = true;
continue;
}
}
}
if (isInLineBreak) // OK to break line here if (isInLineBreak) // OK to break line here
{ {
breakLine(); breakLine();
@ -1255,53 +1313,6 @@ string ASFormatter::nextLine()
resetEndOfStatement(); resetEndOfStatement();
} }
if (currentChar == ':'
&& previousChar != ':' // not part of '::'
&& peekNextChar() != ':') // not part of '::'
{
if (isInCase)
{
isInCase = false;
if (shouldBreakOneLineStatements)
passedColon = true;
}
else if (isCStyle() // for C/C++ only
&& isOkToBreakBlock(bracketTypeStack->back())
&& shouldBreakOneLineStatements
&& !foundQuestionMark // not in a ?: sequence
&& !foundPreDefinitionHeader // not in a definition block (e.g. class foo : public bar
&& previousCommandChar != ')' // not immediately after closing paren of a method header, e.g. ASFormatter::ASFormatter(...) : ASBeautifier(...)
&& !foundPreCommandHeader // not after a 'noexcept'
&& !squareBracketCount // not in objC method call
&& !isInObjCMethodDefinition // not objC '-' or '+' method
&& !isInObjCInterface // not objC @interface
&& !isInObjCSelector // not objC @selector
&& !isDigit(peekNextChar()) // not a bit field
&& !isInEnum // not an enum with a base type
&& !isInAsm // not in extended assembler
&& !isInAsmOneLine // not in extended assembler
&& !isInAsmBlock) // not in extended assembler
{
passedColon = true;
}
if (isCStyle()
&& shouldPadMethodColon
&& (squareBracketCount > 0 || isInObjCMethodDefinition || isInObjCSelector)
&& !foundQuestionMark) // not in a ?: sequence
padObjCMethodColon();
if (isInObjCInterface)
{
appendSpacePad();
if ((int) currentLine.length() > charNum + 1 && !isWhiteSpace(currentLine[charNum + 1]))
currentLine.insert(charNum + 1, " ");
}
if (isClassInitializer())
isInClassInitializer = true;
}
if (currentChar == '?') if (currentChar == '?')
foundQuestionMark = true; foundQuestionMark = true;
@ -1406,7 +1417,6 @@ string ASFormatter::nextLine()
} }
continue; continue;
} // (isPotentialHeader && !isInTemplate) } // (isPotentialHeader && !isInTemplate)
// determine if this is an Objective-C statement // determine if this is an Objective-C statement
@ -1592,7 +1602,6 @@ string ASFormatter::nextLine()
} }
appendCurrentChar(); appendCurrentChar();
} // end of while loop * end of while loop * end of while loop * end of while loop } // end of while loop * end of while loop * end of while loop * end of while loop
// return a beautified (i.e. correctly indented) line. // return a beautified (i.e. correctly indented) line.
@ -2805,6 +2814,9 @@ bool ASFormatter::isPointerOrReference() const
{ {
if (previousNonWSChar == '>') if (previousNonWSChar == '>')
return true; return true;
// This is a logical expression in a pre-definition header
if (foundPreDefinitionHeader)
return false;
string followingText = peekNextText(currentLine.substr(charNum + 2)); string followingText = peekNextText(currentLine.substr(charNum + 2));
if (followingText.length() > 0 && followingText[0] == ')') if (followingText.length() > 0 && followingText[0] == ')')
return true; return true;
@ -3564,7 +3576,7 @@ void ASFormatter::formatPointerOrReference(void)
peekedChar = currentLine[nextChar]; peekedChar = currentLine[nextChar];
} }
// check for cast // check for cast
if (peekedChar == ')' || peekedChar == '>' || peekedChar == ',') if (peekedChar == ')' || peekedChar == '>' || peekedChar == ',' || peekedChar == '.')
{ {
formatPointerOrReferenceCast(); formatPointerOrReferenceCast();
return; return;
@ -7272,5 +7284,4 @@ void ASFormatter::stripCommentPrefix()
} }
} }
} }
} // end namespace astyle } // end namespace astyle

View File

@ -279,7 +279,6 @@ protected: // functions definitions are at the end of ASResource.cpp
bool isCharPotentialOperator(char ch) const; bool isCharPotentialOperator(char ch) const;
bool isDigitSeparator(const string& line, int i) const; bool isDigitSeparator(const string& line, int i) const;
char peekNextChar(const string& line, int i) const; char peekNextChar(const string& line, int i) const;
}; // Class ASBase }; // Class ASBase
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -445,6 +444,7 @@ private: // variables
bool isInStatement; bool isInStatement;
bool isInHeader; bool isInHeader;
bool isInTemplate; bool isInTemplate;
bool isInTemplateInstantiation;
bool isInDefine; bool isInDefine;
bool isInDefineDefinition; bool isInDefineDefinition;
bool classIndent; bool classIndent;
@ -491,6 +491,7 @@ private: // variables
bool foundPreCommandMacro; bool foundPreCommandMacro;
bool shouldAlignMethodColon; bool shouldAlignMethodColon;
bool shouldIndentPreprocConditional; bool shouldIndentPreprocConditional;
bool potentialTemplateDisambiguator;
int indentCount; int indentCount;
int spaceIndentCount; int spaceIndentCount;
int spaceIndentObjCMethodDefinition; int spaceIndentObjCMethodDefinition;
@ -517,6 +518,7 @@ private: // variables
char currentNonSpaceCh; char currentNonSpaceCh;
char currentNonLegalCh; char currentNonLegalCh;
char prevNonLegalCh; char prevNonLegalCh;
char lineFirstChar;
}; // Class ASBeautifier }; // Class ASBeautifier
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -591,7 +593,6 @@ private:
// SQL variables // SQL variables
bool nextLineIsDeclareIndent; // begin declare section indent is reached bool nextLineIsDeclareIndent; // begin declare section indent is reached
bool isInDeclareSection; // need to indent a declare section bool isInDeclareSection; // need to indent a declare section
}; // Class ASEnhancer }; // Class ASEnhancer
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -987,7 +988,6 @@ private: // inline functions
// sort comparison functions for ASResource // sort comparison functions for ASResource
bool sortOnLength(const string* a, const string* b); bool sortOnLength(const string* a, const string* b);
bool sortOnName(const string* a, const string* b); bool sortOnName(const string* a, const string* b);
} // end of astyle namespace } // end of astyle namespace
// end of astyle namespace -------------------------------------------------- // end of astyle namespace --------------------------------------------------

View File

@ -540,12 +540,21 @@ void ASConsole::formatFile(const string& fileName_)
ASStreamIterator<stringstream> streamIterator(&in); ASStreamIterator<stringstream> streamIterator(&in);
formatter.init(&streamIterator); formatter.init(&streamIterator);
// remove targetDirectory from filename if required by print
string displayName;
if (hasWildcard)
displayName = fileName_.substr(targetDirectory.length() + 1);
else
displayName = fileName_;
// format the file // format the file
int currentLine = 0;
while (formatter.hasMoreLines()) while (formatter.hasMoreLines())
{ {
nextLine = formatter.nextLine(); nextLine = formatter.nextLine();
out << nextLine; out << nextLine;
linesOut++; linesOut++;
currentLine++;
if (formatter.hasMoreLines()) if (formatter.hasMoreLines())
{ {
setOutputEOL(lineEndFormat, streamIterator.getOutputEOL()); setOutputEOL(lineEndFormat, streamIterator.getOutputEOL());
@ -562,19 +571,28 @@ void ASConsole::formatFile(const string& fileName_)
nextLine = formatter.nextLine(); nextLine = formatter.nextLine();
out << nextLine; out << nextLine;
linesOut++; linesOut++;
currentLine++;
streamIterator.saveLastInputLine(); streamIterator.saveLastInputLine();
} }
} }
if (filesAreIdentical) if (filesAreIdentical || printChanges)
{ {
if (streamIterator.checkForEmptyLine) if (streamIterator.checkForEmptyLine)
{ {
if (nextLine.find_first_not_of(" \t") != string::npos) if (nextLine.find_first_not_of(" \t") != string::npos)
{
if (printChanges)
printChangedLine(fileName_, nextLine, currentLine);
filesAreIdentical = false; filesAreIdentical = false;
}
} }
else if (!streamIterator.compareToInputBuffer(nextLine)) else if (!streamIterator.compareToInputBuffer(nextLine))
filesAreIdentical = false; {
if (printChanges)
printChangedLine(fileName_, nextLine, currentLine);
filesAreIdentical = false;
}
streamIterator.checkForEmptyLine = false; streamIterator.checkForEmptyLine = false;
} }
} }
@ -585,19 +603,14 @@ void ASConsole::formatFile(const string& fileName_)
filesAreIdentical = false; filesAreIdentical = false;
} }
// remove targetDirectory from filename if required by print
string displayName;
if (hasWildcard)
displayName = fileName_.substr(targetDirectory.length() + 1);
else
displayName = fileName_;
// if file has changed, write the new file // if file has changed, write the new file
if (!filesAreIdentical || streamIterator.getLineEndChange(lineEndFormat)) if (!filesAreIdentical || streamIterator.getLineEndChange(lineEndFormat))
{ {
if (!isDryRun) if (!isDryRun)
writeFile(fileName_, encoding, out); writeFile(fileName_, encoding, out);
printMsg(_("Formatted %s\n"), displayName); printMsg(_("Formatted %s\n"), displayName);
if (printChanges)
printSeparatingLine();
filesFormatted++; filesFormatted++;
} }
else else
@ -610,6 +623,20 @@ void ASConsole::formatFile(const string& fileName_)
assert(formatter.getChecksumDiff() == 0); assert(formatter.getChecksumDiff() == 0);
} }
void ASConsole::printChangedLine(const string& fileName, const string& line, int lineNumber)
{
if (printChanges && !isQuiet)
{
// Print the filename, as this is the first change for file
if (filesAreIdentical)
{
printSeparatingLine();
printf("Changes in %s\n", fileName.c_str());
}
printf("%s(%5d): %s\n", fileName.c_str(), lineNumber, line.c_str());
}
}
// build a vector of argv options // build a vector of argv options
// the program path argv[0] is excluded // the program path argv[0] is excluded
vector<string> ASConsole::getArgvOptions(int argc, char** argv) const vector<string> ASConsole::getArgvOptions(int argc, char** argv) const
@ -662,6 +689,10 @@ bool ASConsole::getIgnoreExcludeErrorsDisplay() const
bool ASConsole::getIsDryRun() const bool ASConsole::getIsDryRun() const
{ return isDryRun; } { return isDryRun; }
// for unit testing
bool ASConsole::getPrintChanges() const
{ return printChanges; }
// for unit testing // for unit testing
bool ASConsole::getIsFormattedOnly() const bool ASConsole::getIsFormattedOnly() const
{ return isFormattedOnly; } { return isFormattedOnly; }
@ -800,6 +831,9 @@ void ASConsole::setIsRecursive(bool state)
void ASConsole::setIsDryRun(bool state) void ASConsole::setIsDryRun(bool state)
{ isDryRun = state; } { isDryRun = state; }
void ASConsole::setPrintChanges(bool state)
{ printChanges = state; }
void ASConsole::setIsVerbose(bool state) void ASConsole::setIsVerbose(bool state)
{ isVerbose = state; } { isVerbose = state; }
@ -1419,7 +1453,9 @@ void ASConsole::getFilePaths(string& filePath)
fprintf(stderr, _("No file to process %s\n"), filePath.c_str()); fprintf(stderr, _("No file to process %s\n"), filePath.c_str());
if (hasWildcard && !isRecursive) if (hasWildcard && !isRecursive)
fprintf(stderr, "%s\n", _("Did you intend to use --recursive")); fprintf(stderr, "%s\n", _("Did you intend to use --recursive"));
error(); // Do not terminate if no match was found for this wildcard
if (!hasWildcard)
error();
} }
if (hasWildcard) if (hasWildcard)
@ -2796,7 +2832,7 @@ void ASOptions::parseOption(const string& arg, const string& errorInfo)
string maxIndentParam = getParam(arg, "M", "max-instatement-indent="); string maxIndentParam = getParam(arg, "M", "max-instatement-indent=");
if (maxIndentParam.length() > 0) if (maxIndentParam.length() > 0)
maxIndent = atoi(maxIndentParam.c_str()); maxIndent = atoi(maxIndentParam.c_str());
if (maxIndent < 40) if (maxIndent < 2 * formatter.getIndentLength())
isOptionError(arg, errorInfo); isOptionError(arg, errorInfo);
else if (maxIndent > 120) else if (maxIndent > 120)
isOptionError(arg, errorInfo); isOptionError(arg, errorInfo);
@ -3137,6 +3173,10 @@ void ASOptions::parseOption(const string& arg, const string& errorInfo)
{ {
g_console->setIsDryRun(true); g_console->setIsDryRun(true);
} }
else if (isOption(arg, "print-changes"))
{
g_console->setPrintChanges(true);
}
else if ( isOption(arg, "Z", "preserve-date") ) else if ( isOption(arg, "Z", "preserve-date") )
{ {
g_console->setPreserveDate(true); g_console->setPreserveDate(true);
@ -3552,7 +3592,6 @@ size_t Utf8_16::utf16ToUtf8(char* utf16In, size_t inLen, bool isBigEndian,
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
} // end of astyle namespace } // end of astyle namespace
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -3807,8 +3846,16 @@ int main(int argc, char** argv)
// process entries in the fileNameVector // process entries in the fileNameVector
g_console->processFiles(); g_console->processFiles();
int return_code = EXIT_SUCCESS;
if (g_console->getPrintChanges() && g_console->getFilesFormatted() > 0)
{
// Use the number of formatted files as a return code with the
// --print-changes option
return_code = g_console->getFilesFormatted();
}
delete g_console; delete g_console;
return EXIT_SUCCESS; return return_code;
} }
#endif // ASTYLE_LIB #endif // ASTYLE_LIB

View File

@ -232,6 +232,7 @@ private: // variables
// command line options // command line options
bool isRecursive; // recursive option bool isRecursive; // recursive option
bool isDryRun; // dry-run option bool isDryRun; // dry-run option
bool printChanges; // print-changes option
bool noBackup; // suffix=none option bool noBackup; // suffix=none option
bool preserveDate; // preserve-date option bool preserveDate; // preserve-date option
bool isVerbose; // verbose option bool isVerbose; // verbose option
@ -307,6 +308,7 @@ public: // functions
bool getIgnoreExcludeErrors() const; bool getIgnoreExcludeErrors() const;
bool getIgnoreExcludeErrorsDisplay() const; bool getIgnoreExcludeErrorsDisplay() const;
bool getIsDryRun() const; bool getIsDryRun() const;
bool getPrintChanges() const;
bool getIsFormattedOnly() const; bool getIsFormattedOnly() const;
bool getIsQuiet() const; bool getIsQuiet() const;
bool getIsRecursive() const; bool getIsRecursive() const;
@ -325,6 +327,7 @@ public: // functions
void setIgnoreExcludeErrors(bool state); void setIgnoreExcludeErrors(bool state);
void setIgnoreExcludeErrorsAndDisplay(bool state); void setIgnoreExcludeErrorsAndDisplay(bool state);
void setIsDryRun(bool state); void setIsDryRun(bool state);
void setPrintChanges(bool state);
void setIsFormattedOnly(bool state); void setIsFormattedOnly(bool state);
void setIsQuiet(bool state); void setIsQuiet(bool state);
void setIsRecursive(bool state); void setIsRecursive(bool state);
@ -347,6 +350,7 @@ private: // functions
ASConsole& operator=(ASConsole&); // not to be implemented ASConsole& operator=(ASConsole&); // not to be implemented
void correctMixedLineEnds(ostringstream& out); void correctMixedLineEnds(ostringstream& out);
void formatFile(const string& fileName_); void formatFile(const string& fileName_);
void printChangedLine(const string& fileName, const string& line, int lineNumber);
string getCurrentDirectory(const string& fileName_) const; string getCurrentDirectory(const string& fileName_) const;
void getFileNames(const string& directory, const string& wildcard); void getFileNames(const string& directory, const string& wildcard);
void getFilePaths(string& filePath); void getFilePaths(string& filePath);