From a28cde54250d21debddc99d40445b50e20c97513 Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Sat, 10 Sep 2016 03:25:39 +0200 Subject: [PATCH 01/19] Do not dedent comments in multiline class headers + Do not add InStatementIndent for commas in class headers --- src/ASBeautifier.cpp | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/ASBeautifier.cpp b/src/ASBeautifier.cpp index 61bf441..ee63aa6 100644 --- a/src/ASBeautifier.cpp +++ b/src/ASBeautifier.cpp @@ -2097,21 +2097,13 @@ void ASBeautifier::computePreliminaryIndentation() ++indentCount; isInSwitch = true; } - } // end of for loop if (isInClassHeader) { if (!isJavaStyle()) isInClassHeaderTab = true; - if (lineOpensWithLineComment || lineStartsInComment || lineOpensWithComment) - { - if (!lineBeginsWithOpenBracket) - --indentCount; - if (!inStatementIndentStack->empty()) - spaceIndentCount -= inStatementIndentStack->back(); - } - else if (blockIndent) + if (blockIndent) { if (!lineBeginsWithOpenBracket) ++indentCount; @@ -2979,7 +2971,6 @@ void ASBeautifier::parseCurrentLine(const string& line) if (isSharpStyle() && findKeyword(line, i, AS_LET)) isInLet = true; - } // isPotentialHeader if (ch == '?') @@ -3103,7 +3094,8 @@ void ASBeautifier::parseCurrentLine(const string& line) // do nothing for now } // 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 inStatementIndent = prevWord + spaceIndentCount + tabIncrementIn; @@ -3479,5 +3471,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 namespace astyle From 25c4fdac73bbb49517c146d966cf67f40f46d829 Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Sat, 10 Sep 2016 04:29:09 +0200 Subject: [PATCH 02/19] Add firstLineChar member in ASBeautifier + Use symmetrical layout for closing brace in template argument list: template < class Argument > --- src/ASBeautifier.cpp | 19 +++++++++++++++++++ src/astyle.h | 4 +--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/ASBeautifier.cpp b/src/ASBeautifier.cpp index ee63aa6..98a6e33 100644 --- a/src/ASBeautifier.cpp +++ b/src/ASBeautifier.cpp @@ -252,6 +252,7 @@ ASBeautifier::ASBeautifier(const ASBeautifier& other) : ASBase(other) currentNonSpaceCh = other.currentNonSpaceCh; currentNonLegalCh = other.currentNonLegalCh; prevNonLegalCh = other.prevNonLegalCh; + lineFirstChar = other.lineFirstChar; } /** @@ -365,6 +366,7 @@ void ASBeautifier::init(ASSourceIterator* iter) prevNonLegalCh = '{'; currentNonLegalCh = '{'; quoteChar = ' '; + lineFirstChar = ' '; probationHeader = NULL; lastLineHeader = NULL; backslashEndsPrevLine = false; @@ -879,6 +881,7 @@ string ASBeautifier::beautify(const string& originalLine) haveLineContinuationChar = false; lineOpeningBlocksNum = 0; lineClosingBlocksNum = 0; + lineFirstChar = ' '; if (isImmediatelyPostObjCMethodDefinition) clearObjCMethodDefinitionAlignment(); @@ -920,6 +923,7 @@ string ASBeautifier::beautify(const string& originalLine) line = trim(originalLine); if (line.length() > 0) { + lineFirstChar = line[0]; if (line[0] == '{') lineBeginsWithOpenBracket = true; else if (line[0] == '}') @@ -2110,6 +2114,21 @@ void ASBeautifier::computePreliminaryIndentation() } } + if (isInTemplate) + { + // 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) { indentCount += classInitializerIndents; diff --git a/src/astyle.h b/src/astyle.h index c910942..0a10072 100644 --- a/src/astyle.h +++ b/src/astyle.h @@ -279,7 +279,6 @@ protected: // functions definitions are at the end of ASResource.cpp bool isCharPotentialOperator(char ch) const; bool isDigitSeparator(const string& line, int i) const; char peekNextChar(const string& line, int i) const; - }; // Class ASBase //----------------------------------------------------------------------------- @@ -517,6 +516,7 @@ private: // variables char currentNonSpaceCh; char currentNonLegalCh; char prevNonLegalCh; + char lineFirstChar; }; // Class ASBeautifier //----------------------------------------------------------------------------- @@ -591,7 +591,6 @@ private: // SQL variables bool nextLineIsDeclareIndent; // begin declare section indent is reached bool isInDeclareSection; // need to indent a declare section - }; // Class ASEnhancer //----------------------------------------------------------------------------- @@ -987,7 +986,6 @@ private: // inline functions // sort comparison functions for ASResource bool sortOnLength(const string* a, const string* b); bool sortOnName(const string* a, const string* b); - } // end of astyle namespace // end of astyle namespace -------------------------------------------------- From 52a1be339aa4a1fad051133062c4a547aab7b8d2 Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Sat, 10 Sep 2016 04:54:08 +0200 Subject: [PATCH 03/19] Fix false detection of rvalue references in a class headers --- src/ASFormatter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ASFormatter.cpp b/src/ASFormatter.cpp index c41ffe8..b0fd42e 100644 --- a/src/ASFormatter.cpp +++ b/src/ASFormatter.cpp @@ -1406,7 +1406,6 @@ string ASFormatter::nextLine() } continue; - } // (isPotentialHeader && !isInTemplate) // determine if this is an Objective-C statement @@ -1592,7 +1591,6 @@ string ASFormatter::nextLine() } appendCurrentChar(); - } // end of while loop * end of while loop * end of while loop * end of while loop // return a beautified (i.e. correctly indented) line. @@ -2805,6 +2803,9 @@ bool ASFormatter::isPointerOrReference() const { if (previousNonWSChar == '>') return true; + // This is a logical expression in a pre-definition header + if (foundPreDefinitionHeader) + return false; string followingText = peekNextText(currentLine.substr(charNum + 2)); if (followingText.length() > 0 && followingText[0] == ')') return true; @@ -7272,5 +7273,4 @@ void ASFormatter::stripCommentPrefix() } } } - } // end namespace astyle From f3cd3f7c51a87fa69b5055fa2ea5a4832256d8ab Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Sat, 10 Sep 2016 04:55:59 +0200 Subject: [PATCH 04/19] Allow max-instatement-indent to be less than 40 --- src/astyle_main.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/astyle_main.cpp b/src/astyle_main.cpp index 16a0c4b..567370c 100644 --- a/src/astyle_main.cpp +++ b/src/astyle_main.cpp @@ -2796,7 +2796,7 @@ void ASOptions::parseOption(const string& arg, const string& errorInfo) string maxIndentParam = getParam(arg, "M", "max-instatement-indent="); if (maxIndentParam.length() > 0) maxIndent = atoi(maxIndentParam.c_str()); - if (maxIndent < 40) + if (maxIndent < 2 * formatter.getIndentLength()) isOptionError(arg, errorInfo); else if (maxIndent > 120) isOptionError(arg, errorInfo); @@ -3552,7 +3552,6 @@ size_t Utf8_16::utf16ToUtf8(char* utf16In, size_t inLen, bool isBigEndian, } //---------------------------------------------------------------------------- - } // end of astyle namespace //---------------------------------------------------------------------------- From 1bad21fe6b6d316f3573cb0873cc60588e86c399 Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Tue, 13 Sep 2016 02:19:29 +0200 Subject: [PATCH 05/19] Provide basic indentation for template instantiation argument lists --- src/ASBeautifier.cpp | 104 +++++++++++++++++++++++++++++++++---------- src/astyle.h | 1 + 2 files changed, 81 insertions(+), 24 deletions(-) diff --git a/src/ASBeautifier.cpp b/src/ASBeautifier.cpp index 98a6e33..97d35a0 100644 --- a/src/ASBeautifier.cpp +++ b/src/ASBeautifier.cpp @@ -180,6 +180,7 @@ ASBeautifier::ASBeautifier(const ASBeautifier& other) : ASBase(other) isInStatement = other.isInStatement; isInHeader = other.isInHeader; isInTemplate = other.isInTemplate; + isInTemplateInstantiation = other.isInTemplateInstantiation; isInDefine = other.isInDefine; isInDefineDefinition = other.isInDefineDefinition; classIndent = other.classIndent; @@ -345,6 +346,7 @@ void ASBeautifier::init(ASSourceIterator* iter) isInLet = false; isInHeader = false; isInTemplate = false; + isInTemplateInstantiation = false; isInConditional = false; indentCount = 0; @@ -2114,7 +2116,7 @@ void ASBeautifier::computePreliminaryIndentation() } } - if (isInTemplate) + if (isInTemplate || isInTemplateInstantiation) { // Use symmetrical layout for closing brace in template argument list: // @@ -2123,10 +2125,10 @@ void ASBeautifier::computePreliminaryIndentation() // class Argument // > if (lineFirstChar == '>' && !lineStartsInComment) - { + { if (!inStatementIndentStack->empty()) spaceIndentCount -= inStatementIndentStack->back(); - } + } } if (isInClassInitializer || isInEnumTypeID) @@ -2576,27 +2578,67 @@ void ASBeautifier::parseCurrentLine(const string& line) else currentHeader = NULL; - if (isCStyle() && isInTemplate + if (isCStyle() && (ch == '<' || ch == '>') && !(line.length() > i + 1 && line.compare(i, 2, ">=") == 0)) { - if (ch == '<') - { - ++templateDepth; - inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size()); - registerInStatementIndent(line, i, spaceIndentCount, tabIncrementIn, 0, true); - } - else if (ch == '>') - { - popLastInStatementIndent(); - if (--templateDepth <= 0) - { - ch = ';'; - isInTemplate = false; - templateDepth = 0; - } - } - } + if (isInTemplate) + { + if (ch == '<') + { + ++templateDepth; + inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size()); + registerInStatementIndent(line, i, spaceIndentCount, tabIncrementIn, 0, true); + } + else if (ch == '>') + { + popLastInStatementIndent(); + if (--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) + { + ch = ';'; + isInTemplateInstantiation = false; + templateDepth = 0; + } + } + } + } + + // handle parentheses if (ch == '(' || ch == '[' || ch == ')' || ch == ']') @@ -3085,10 +3127,13 @@ void ASBeautifier::parseCurrentLine(const string& line) } 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()) + { inStatementIndentStack->pop_back(); - + } + } else if (ch == ',' && isInEnum && isNonInStatementArray && !inStatementIndentStack->empty()) inStatementIndentStack->pop_back(); @@ -3234,7 +3279,17 @@ void ASBeautifier::parseCurrentLine(const string& line) } if (parenDepth == 0 && ch == ';') + { 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) isImmediatelyPostObjCMethodDefinition = true; @@ -3411,7 +3466,8 @@ void ASBeautifier::parseCurrentLine(const string& line) if (foundNonAssignmentOp == &AS_LAMBDA) foundPreCommandHeader = true; - if (isInTemplate && foundNonAssignmentOp == &AS_GR_GR) + if ((isInTemplate || isInTemplateInstantiation) + && foundNonAssignmentOp == &AS_GR_GR) foundNonAssignmentOp = NULL; // Since findHeader's boundary checking was not used above, it is possible diff --git a/src/astyle.h b/src/astyle.h index 0a10072..73e0fff 100644 --- a/src/astyle.h +++ b/src/astyle.h @@ -444,6 +444,7 @@ private: // variables bool isInStatement; bool isInHeader; bool isInTemplate; + bool isInTemplateInstantiation; bool isInDefine; bool isInDefineDefinition; bool classIndent; From 91bff90bf2f00622bc8054c8bbabc9ae9c362345 Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Wed, 14 Sep 2016 03:46:07 +0200 Subject: [PATCH 06/19] Attach colon to constructor header and break line before member initializers --- src/ASFormatter.cpp | 105 ++++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 47 deletions(-) diff --git a/src/ASFormatter.cpp b/src/ASFormatter.cpp index b0fd42e..2a58da2 100644 --- a/src/ASFormatter.cpp +++ b/src/ASFormatter.cpp @@ -1209,6 +1209,64 @@ string ASFormatter::nextLine() } } // (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 { breakLine(); @@ -1255,53 +1313,6 @@ string ASFormatter::nextLine() 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 == '?') foundQuestionMark = true; From 8458be2f70c134cb24ca3bdecc8f8f436b121299 Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Wed, 14 Sep 2016 20:19:13 +0200 Subject: [PATCH 07/19] Add --print-changes to print all changed lines (useful in dry-run mode) + Return the number of formatted files in this mode --- src/astyle_main.cpp | 63 ++++++++++++++++++++++++++++++++++++++------- src/astyle_main.h | 4 +++ 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/src/astyle_main.cpp b/src/astyle_main.cpp index 567370c..952340c 100644 --- a/src/astyle_main.cpp +++ b/src/astyle_main.cpp @@ -540,6 +540,13 @@ void ASConsole::formatFile(const string& fileName_) ASStreamIterator streamIterator(&in); 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 while (formatter.hasMoreLines()) { @@ -566,15 +573,23 @@ void ASConsole::formatFile(const string& fileName_) } } - if (filesAreIdentical) + if (filesAreIdentical || printChanges) { if (streamIterator.checkForEmptyLine) { if (nextLine.find_first_not_of(" \t") != string::npos) + { + if (printChanges) + printChangedLine(displayName, nextLine, linesOut); filesAreIdentical = false; + } } else if (!streamIterator.compareToInputBuffer(nextLine)) - filesAreIdentical = false; + { + if (printChanges) + printChangedLine(displayName, nextLine, linesOut); + filesAreIdentical = false; + } streamIterator.checkForEmptyLine = false; } } @@ -585,19 +600,14 @@ void ASConsole::formatFile(const string& fileName_) 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 (!filesAreIdentical || streamIterator.getLineEndChange(lineEndFormat)) { if (!isDryRun) writeFile(fileName_, encoding, out); printMsg(_("Formatted %s\n"), displayName); + if (printChanges) + printSeparatingLine(); filesFormatted++; } else @@ -610,6 +620,20 @@ void ASConsole::formatFile(const string& fileName_) 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("Line %5d: %s\n", lineNumber, line.c_str()); + } +} + // build a vector of argv options // the program path argv[0] is excluded vector ASConsole::getArgvOptions(int argc, char** argv) const @@ -662,6 +686,10 @@ bool ASConsole::getIgnoreExcludeErrorsDisplay() const bool ASConsole::getIsDryRun() const { return isDryRun; } +// for unit testing +bool ASConsole::getPrintChanges() const +{ return printChanges; } + // for unit testing bool ASConsole::getIsFormattedOnly() const { return isFormattedOnly; } @@ -800,6 +828,9 @@ void ASConsole::setIsRecursive(bool state) void ASConsole::setIsDryRun(bool state) { isDryRun = state; } +void ASConsole::setPrintChanges(bool state) +{ printChanges = state; } + void ASConsole::setIsVerbose(bool state) { isVerbose = state; } @@ -3137,6 +3168,10 @@ void ASOptions::parseOption(const string& arg, const string& errorInfo) { g_console->setIsDryRun(true); } + else if (isOption(arg, "print-changes")) + { + g_console->setPrintChanges(true); + } else if ( isOption(arg, "Z", "preserve-date") ) { g_console->setPreserveDate(true); @@ -3806,8 +3841,16 @@ int main(int argc, char** argv) // process entries in the fileNameVector 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; - return EXIT_SUCCESS; + return return_code; } #endif // ASTYLE_LIB diff --git a/src/astyle_main.h b/src/astyle_main.h index bfbc0e2..43d5fd2 100644 --- a/src/astyle_main.h +++ b/src/astyle_main.h @@ -232,6 +232,7 @@ private: // variables // command line options bool isRecursive; // recursive option bool isDryRun; // dry-run option + bool printChanges; // print-changes option bool noBackup; // suffix=none option bool preserveDate; // preserve-date option bool isVerbose; // verbose option @@ -307,6 +308,7 @@ public: // functions bool getIgnoreExcludeErrors() const; bool getIgnoreExcludeErrorsDisplay() const; bool getIsDryRun() const; + bool getPrintChanges() const; bool getIsFormattedOnly() const; bool getIsQuiet() const; bool getIsRecursive() const; @@ -325,6 +327,7 @@ public: // functions void setIgnoreExcludeErrors(bool state); void setIgnoreExcludeErrorsAndDisplay(bool state); void setIsDryRun(bool state); + void setPrintChanges(bool state); void setIsFormattedOnly(bool state); void setIsQuiet(bool state); void setIsRecursive(bool state); @@ -347,6 +350,7 @@ private: // functions ASConsole& operator=(ASConsole&); // not to be implemented void correctMixedLineEnds(ostringstream& out); void formatFile(const string& fileName_); + void printChangedLine(const string& fileName, const string& line, int lineNumber); string getCurrentDirectory(const string& fileName_) const; void getFileNames(const string& directory, const string& wildcard); void getFilePaths(string& filePath); From d11eb1a63da7420255dab3dcc68c76950ee167b9 Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Wed, 14 Sep 2016 20:43:41 +0200 Subject: [PATCH 08/19] Do not terminate if no matching file was found for a wildcard --- src/astyle_main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/astyle_main.cpp b/src/astyle_main.cpp index 952340c..bb30b76 100644 --- a/src/astyle_main.cpp +++ b/src/astyle_main.cpp @@ -1450,7 +1450,9 @@ void ASConsole::getFilePaths(string& filePath) fprintf(stderr, _("No file to process %s\n"), filePath.c_str()); if (hasWildcard && !isRecursive) 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) From 53696ac249b98d7e925689c4264958c5b0fb9bef Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Wed, 14 Sep 2016 21:55:53 +0200 Subject: [PATCH 09/19] Do not add extra space in variadic template argument: Args&&... args --- src/ASFormatter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ASFormatter.cpp b/src/ASFormatter.cpp index 2a58da2..8933c1f 100644 --- a/src/ASFormatter.cpp +++ b/src/ASFormatter.cpp @@ -3576,7 +3576,7 @@ void ASFormatter::formatPointerOrReference(void) peekedChar = currentLine[nextChar]; } // check for cast - if (peekedChar == ')' || peekedChar == '>' || peekedChar == ',') + if (peekedChar == ')' || peekedChar == '>' || peekedChar == ',' || peekedChar == '.') { formatPointerOrReferenceCast(); return; From b1259192ff10a488703ce37343e60e83b44bda13 Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Thu, 15 Sep 2016 02:07:08 +0200 Subject: [PATCH 10/19] Do not try to align multiple assignments if line ends with comma --- src/ASBeautifier.cpp | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/src/ASBeautifier.cpp b/src/ASBeautifier.cpp index 97d35a0..9eaf53f 100644 --- a/src/ASBeautifier.cpp +++ b/src/ASBeautifier.cpp @@ -2347,7 +2347,6 @@ void ASBeautifier::parseCurrentLine(const string& line) bool isInOperator = false; bool isSpecialChar = false; bool haveCaseIndent = false; - bool haveAssignmentThisLine = false; bool closingBracketReached = false; bool previousLineProbation = (probationHeader != NULL); char ch = ' '; @@ -3514,23 +3513,8 @@ void ASBeautifier::parseCurrentLine(const string& line) 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' - else if (isInLet) + if (isInLet) { isInLet = false; } From e4ce7b36b010b1de6d56dfad3d364fdeb1615641 Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Thu, 15 Sep 2016 03:06:06 +0200 Subject: [PATCH 11/19] Do not recognize the "template" disambiguator for dependent names as an actual template header --- src/ASBeautifier.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/ASBeautifier.cpp b/src/ASBeautifier.cpp index 9eaf53f..3adcb3a 100644 --- a/src/ASBeautifier.cpp +++ b/src/ASBeautifier.cpp @@ -2871,6 +2871,18 @@ void ASBeautifier::parseCurrentLine(const string& line) && ASBeautifier::peekNextChar(line, i + (*newHeader).length() - 1) != '(') newHeader = NULL; + // The "template" disambiguator for dependent names should not be + // recognized as an actual template header. For example: + // T::template foo() + // s.template foo(); + // this->template foo(); + if (newHeader == &AS_TEMPLATE + && (prevNonSpaceCh == ':' || prevNonSpaceCh == '.' + || prevNonSpaceCh == '-')) + { + newHeader = NULL; + } + if (newHeader != NULL) { // if we reached here, then this is a header... From 03668a9b21c484e410ec6cc95eedbecb4a9c8a50 Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Thu, 15 Sep 2016 17:34:14 +0200 Subject: [PATCH 12/19] Fix line numbers with --print-changes --- src/astyle_main.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/astyle_main.cpp b/src/astyle_main.cpp index bb30b76..cf265a6 100644 --- a/src/astyle_main.cpp +++ b/src/astyle_main.cpp @@ -548,11 +548,13 @@ void ASConsole::formatFile(const string& fileName_) displayName = fileName_; // format the file + int currentLine = 0; while (formatter.hasMoreLines()) { nextLine = formatter.nextLine(); out << nextLine; linesOut++; + currentLine++; if (formatter.hasMoreLines()) { setOutputEOL(lineEndFormat, streamIterator.getOutputEOL()); @@ -569,6 +571,7 @@ void ASConsole::formatFile(const string& fileName_) nextLine = formatter.nextLine(); out << nextLine; linesOut++; + currentLine++; streamIterator.saveLastInputLine(); } } @@ -580,14 +583,14 @@ void ASConsole::formatFile(const string& fileName_) if (nextLine.find_first_not_of(" \t") != string::npos) { if (printChanges) - printChangedLine(displayName, nextLine, linesOut); + printChangedLine(displayName, nextLine, currentLine); filesAreIdentical = false; } } else if (!streamIterator.compareToInputBuffer(nextLine)) { if (printChanges) - printChangedLine(displayName, nextLine, linesOut); + printChangedLine(displayName, nextLine, currentLine); filesAreIdentical = false; } streamIterator.checkForEmptyLine = false; From c43ddc6964ad214699ce047bb414389666d909fc Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Thu, 15 Sep 2016 19:33:20 +0200 Subject: [PATCH 13/19] Revert template disambiguator fix --- src/ASBeautifier.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/ASBeautifier.cpp b/src/ASBeautifier.cpp index 3adcb3a..9eaf53f 100644 --- a/src/ASBeautifier.cpp +++ b/src/ASBeautifier.cpp @@ -2871,18 +2871,6 @@ void ASBeautifier::parseCurrentLine(const string& line) && ASBeautifier::peekNextChar(line, i + (*newHeader).length() - 1) != '(') newHeader = NULL; - // The "template" disambiguator for dependent names should not be - // recognized as an actual template header. For example: - // T::template foo() - // s.template foo(); - // this->template foo(); - if (newHeader == &AS_TEMPLATE - && (prevNonSpaceCh == ':' || prevNonSpaceCh == '.' - || prevNonSpaceCh == '-')) - { - newHeader = NULL; - } - if (newHeader != NULL) { // if we reached here, then this is a header... From 1548f1d070112e2f2be92ad5794f93aee26ceafe Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Thu, 15 Sep 2016 20:39:58 +0200 Subject: [PATCH 14/19] Do not recognize the "template" disambiguator for dependent names as an actual template header --- src/ASBeautifier.cpp | 33 +++++++++++++++++++++++++++++++++ src/astyle.h | 1 + 2 files changed, 34 insertions(+) diff --git a/src/ASBeautifier.cpp b/src/ASBeautifier.cpp index 9eaf53f..f49ae16 100644 --- a/src/ASBeautifier.cpp +++ b/src/ASBeautifier.cpp @@ -227,6 +227,7 @@ ASBeautifier::ASBeautifier(const ASBeautifier& other) : ASBase(other) shouldAlignMethodColon = other.shouldAlignMethodColon; shouldIndentPreprocDefine = other.shouldIndentPreprocDefine; shouldIndentPreprocConditional = other.shouldIndentPreprocConditional; + potentialTemplateDisambiguator = other.potentialTemplateDisambiguator; indentCount = other.indentCount; spaceIndentCount = other.spaceIndentCount; spaceIndentObjCMethodDefinition = other.spaceIndentObjCMethodDefinition; @@ -348,6 +349,7 @@ void ASBeautifier::init(ASSourceIterator* iter) isInTemplate = false; isInTemplateInstantiation = false; isInConditional = false; + potentialTemplateDisambiguator = false; indentCount = 0; spaceIndentCount = 0; @@ -2561,6 +2563,14 @@ void ASBeautifier::parseCurrentLine(const string& line) 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; currentNonSpaceCh = ch; if (!isLegalNameChar(ch) && ch != ',' && ch != ';') @@ -2871,6 +2881,18 @@ void ASBeautifier::parseCurrentLine(const string& line) && ASBeautifier::peekNextChar(line, i + (*newHeader).length() - 1) != '(') newHeader = NULL; + // The "template" disambiguator for dependent names should not + // be recognized as an actual template header. For example: + // T::template foo() + // s.template foo(); + // this->template foo(); + if (isCStyle() && newHeader == &AS_TEMPLATE + && (potentialTemplateDisambiguator || prevNonSpaceCh == '.')) + { + newHeader = NULL; + potentialTemplateDisambiguator = false; + } + if (newHeader != NULL) { // if we reached here, then this is a header... @@ -3042,6 +3064,9 @@ void ASBeautifier::parseCurrentLine(const string& line) if (line.length() > i + 1 && line[i + 1] == ':') // look for :: { ++i; + // The next word might be a template disambiguator like + // T::template foo() + potentialTemplateDisambiguator = true; continue; } else if (isInQuestion) @@ -3486,6 +3511,14 @@ void ASBeautifier::parseCurrentLine(const string& line) if (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(); + if (isCStyle() && foundNonAssignmentOp == &AS_ARROW) + { + potentialTemplateDisambiguator = true; + } + // For C++ input/output, operator<< and >> should be // aligned, if we are not in a statement already and // also not in the "operator<<(...)" header line diff --git a/src/astyle.h b/src/astyle.h index 73e0fff..4af6a0d 100644 --- a/src/astyle.h +++ b/src/astyle.h @@ -491,6 +491,7 @@ private: // variables bool foundPreCommandMacro; bool shouldAlignMethodColon; bool shouldIndentPreprocConditional; + bool potentialTemplateDisambiguator; int indentCount; int spaceIndentCount; int spaceIndentObjCMethodDefinition; From 5d24aeba9a335aadf4261e25f2339fef1ce7df25 Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Thu, 15 Sep 2016 21:12:46 +0200 Subject: [PATCH 15/19] Fix issue when closing potential template instantiation --- src/ASBeautifier.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ASBeautifier.cpp b/src/ASBeautifier.cpp index f49ae16..4bc502f 100644 --- a/src/ASBeautifier.cpp +++ b/src/ASBeautifier.cpp @@ -2639,7 +2639,6 @@ void ASBeautifier::parseCurrentLine(const string& line) } if (--templateDepth <= 0) { - ch = ';'; isInTemplateInstantiation = false; templateDepth = 0; } From 39a611a2e817db7f07e4c9f880333d84cc7e86ca Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Thu, 15 Sep 2016 21:31:44 +0200 Subject: [PATCH 16/19] Fix invalid detection of >> in class headers --- src/ASBeautifier.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ASBeautifier.cpp b/src/ASBeautifier.cpp index 4bc502f..827ba42 100644 --- a/src/ASBeautifier.cpp +++ b/src/ASBeautifier.cpp @@ -3521,7 +3521,7 @@ void ASBeautifier::parseCurrentLine(const string& line) // For C++ input/output, operator<< and >> should be // aligned, if we are not in a statement already and // also not in the "operator<<(...)" header line - if (!isInOperator + if (!isInOperator && !isInClassHeader && inStatementIndentStack->empty() && isCStyle() && (foundNonAssignmentOp == &AS_GR_GR From eb505347cbe83c22498cee3356da3fda62903ff0 Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Fri, 16 Sep 2016 19:44:47 +0200 Subject: [PATCH 17/19] Keep spaceIndentCount for the current line to handle lambda expressions in multiline statements: std::generate(data.begin(), data.end(), [&]() { return randval(engine); }); --- src/ASBeautifier.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/ASBeautifier.cpp b/src/ASBeautifier.cpp index 827ba42..2d1276c 100644 --- a/src/ASBeautifier.cpp +++ b/src/ASBeautifier.cpp @@ -2836,7 +2836,13 @@ void ASBeautifier::parseCurrentLine(const string& line) if (lineBeginsWithOpenBracket || lineBeginsWithComma) 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; } From c9a243fd41a43bb7717f293bb69d30b0737f2aa7 Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Fri, 16 Sep 2016 19:53:37 +0200 Subject: [PATCH 18/19] Print full filenames with --print-changes (so the IDE can jump to the line) --- src/astyle_main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/astyle_main.cpp b/src/astyle_main.cpp index cf265a6..0ddb7d0 100644 --- a/src/astyle_main.cpp +++ b/src/astyle_main.cpp @@ -583,14 +583,14 @@ void ASConsole::formatFile(const string& fileName_) if (nextLine.find_first_not_of(" \t") != string::npos) { if (printChanges) - printChangedLine(displayName, nextLine, currentLine); + printChangedLine(fileName_, nextLine, currentLine); filesAreIdentical = false; } } else if (!streamIterator.compareToInputBuffer(nextLine)) { if (printChanges) - printChangedLine(displayName, nextLine, currentLine); + printChangedLine(fileName_, nextLine, currentLine); filesAreIdentical = false; } streamIterator.checkForEmptyLine = false; @@ -633,7 +633,7 @@ void ASConsole::printChangedLine(const string& fileName, const string& line, int printSeparatingLine(); printf("Changes in %s\n", fileName.c_str()); } - printf("Line %5d: %s\n", lineNumber, line.c_str()); + printf("%s(%5d): %s\n", fileName.c_str(), lineNumber, line.c_str()); } } From 5c9aefd388a6d1f2bbbd57f3e09ed9e474a3955c Mon Sep 17 00:00:00 2001 From: Peter Vingelmann Date: Fri, 16 Sep 2016 20:58:01 +0200 Subject: [PATCH 19/19] registerInStatementIndent: Align with the next non-whitespace character --- src/ASBeautifier.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/ASBeautifier.cpp b/src/ASBeautifier.cpp index 2d1276c..72f0cc5 100644 --- a/src/ASBeautifier.cpp +++ b/src/ASBeautifier.cpp @@ -1261,10 +1261,12 @@ void ASBeautifier::registerInStatementIndent(const string& line, int i, int spac int tabIncrementIn, int minIndent, bool updateParenStack) { 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 (nextNonWSChar == remainingCharNum) + if (nextProgramChar == remainingCharNum) { int previousIndent = spaceTabCount_; if (!inStatementIndentStack->empty()) @@ -1279,6 +1281,13 @@ void ASBeautifier::registerInStatementIndent(const string& line, int i, int spac 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) parenIndentStack->push_back(i + spaceTabCount_ - horstmannIndentInStatement);