summaryrefslogtreecommitdiff
path: root/thirdparty/astyle/ASBeautifier.cpp
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2017-05-09 15:28:09 +0200
committerEven Rouault <even.rouault@spatialys.com>2017-05-09 20:46:16 +0200
commitd4e54e9f35d532062533f1d369c159810b01d224 (patch)
tree7046ff72a41a8b0ad2e40e1d4aa3b191d03f6380 /thirdparty/astyle/ASBeautifier.cpp
parent8650b70e06408d394c1708846b6fc2d86cf14079 (diff)
Add mechanisms to reformant and check code style (#128)
Use an internal version of astyle (astyle 3.0). Scripts taken from QGIS. astyle.options from https://github.com/uclouvain/openjpeg/issues/128 scripts/prepare-commit.sh can be used locally to automatically reformat edited files. Travis-CI will run scripts/verify-indentation.sh to verify committed files.
Diffstat (limited to 'thirdparty/astyle/ASBeautifier.cpp')
-rwxr-xr-xthirdparty/astyle/ASBeautifier.cpp3659
1 files changed, 3659 insertions, 0 deletions
diff --git a/thirdparty/astyle/ASBeautifier.cpp b/thirdparty/astyle/ASBeautifier.cpp
new file mode 100755
index 00000000..25b2e53f
--- /dev/null
+++ b/thirdparty/astyle/ASBeautifier.cpp
@@ -0,0 +1,3659 @@
+// ASBeautifier.cpp
+// Copyright (c) 2017 by Jim Pattee <jimp03@email.com>.
+// This code is licensed under the MIT License.
+// License.md describes the conditions under which this software may be distributed.
+
+//-----------------------------------------------------------------------------
+// headers
+//-----------------------------------------------------------------------------
+
+#include "astyle.h"
+
+#include <algorithm>
+
+//-----------------------------------------------------------------------------
+// astyle namespace
+//-----------------------------------------------------------------------------
+
+namespace astyle {
+//
+// this must be global
+static int g_preprocessorCppExternCBrace;
+
+//-----------------------------------------------------------------------------
+// ASBeautifier class
+//-----------------------------------------------------------------------------
+
+/**
+ * ASBeautifier's constructor
+ * This constructor is called only once for each source file.
+ * The cloned ASBeautifier objects are created with the copy constructor.
+ */
+ASBeautifier::ASBeautifier()
+{
+ waitingBeautifierStack = nullptr;
+ activeBeautifierStack = nullptr;
+ waitingBeautifierStackLengthStack = nullptr;
+ activeBeautifierStackLengthStack = nullptr;
+
+ headerStack = nullptr;
+ tempStacks = nullptr;
+ squareBracketDepthStack = nullptr;
+ blockStatementStack = nullptr;
+ parenStatementStack = nullptr;
+ braceBlockStateStack = nullptr;
+ continuationIndentStack = nullptr;
+ continuationIndentStackSizeStack = nullptr;
+ parenIndentStack = nullptr;
+ preprocIndentStack = nullptr;
+ sourceIterator = nullptr;
+ isModeManuallySet = false;
+ shouldForceTabIndentation = false;
+ setSpaceIndentation(4);
+ setContinuationIndentation(1);
+ setMinConditionalIndentOption(MINCOND_TWO);
+ setMaxContinuationIndentLength(40);
+ classInitializerIndents = 1;
+ tabLength = 0;
+ setClassIndent(false);
+ setModifierIndent(false);
+ setSwitchIndent(false);
+ setCaseIndent(false);
+ setBlockIndent(false);
+ setBraceIndent(false);
+ setBraceIndentVtk(false);
+ setNamespaceIndent(false);
+ setAfterParenIndent(false);
+ setLabelIndent(false);
+ setEmptyLineFill(false);
+ setCStyle();
+ setPreprocDefineIndent(false);
+ setPreprocConditionalIndent(false);
+ setAlignMethodColon(false);
+
+ // initialize ASBeautifier member vectors
+ beautifierFileType = 9; // reset to an invalid type
+ headers = new vector<const string*>;
+ nonParenHeaders = new vector<const string*>;
+ assignmentOperators = new vector<const string*>;
+ nonAssignmentOperators = new vector<const string*>;
+ preBlockStatements = new vector<const string*>;
+ preCommandHeaders = new vector<const string*>;
+ indentableHeaders = new vector<const string*>;
+}
+
+/**
+ * ASBeautifier's copy constructor
+ * Copy the vector objects to vectors in the new ASBeautifier
+ * object so the new object can be destroyed without deleting
+ * the vector objects in the copied vector.
+ * This is the reason a copy constructor is needed.
+ *
+ * Must explicitly call the base class copy constructor.
+ */
+ASBeautifier::ASBeautifier(const ASBeautifier& other) : ASBase(other)
+{
+ // these don't need to copy the stack
+ waitingBeautifierStack = nullptr;
+ activeBeautifierStack = nullptr;
+ waitingBeautifierStackLengthStack = nullptr;
+ activeBeautifierStackLengthStack = nullptr;
+
+ // vector '=' operator performs a DEEP copy of all elements in the vector
+
+ headerStack = new vector<const string*>;
+ *headerStack = *other.headerStack;
+
+ tempStacks = copyTempStacks(other);
+
+ squareBracketDepthStack = new vector<int>;
+ *squareBracketDepthStack = *other.squareBracketDepthStack;
+
+ blockStatementStack = new vector<bool>;
+ *blockStatementStack = *other.blockStatementStack;
+
+ parenStatementStack = new vector<bool>;
+ *parenStatementStack = *other.parenStatementStack;
+
+ braceBlockStateStack = new vector<bool>;
+ *braceBlockStateStack = *other.braceBlockStateStack;
+
+ continuationIndentStack = new vector<int>;
+ *continuationIndentStack = *other.continuationIndentStack;
+
+ continuationIndentStackSizeStack = new vector<int>;
+ *continuationIndentStackSizeStack = *other.continuationIndentStackSizeStack;
+
+ parenIndentStack = new vector<int>;
+ *parenIndentStack = *other.parenIndentStack;
+
+ preprocIndentStack = new vector<pair<int, int> >;
+ *preprocIndentStack = *other.preprocIndentStack;
+
+ // Copy the pointers to vectors.
+ // This is ok because the original ASBeautifier object
+ // is not deleted until end of job.
+ beautifierFileType = other.beautifierFileType;
+ headers = other.headers;
+ nonParenHeaders = other.nonParenHeaders;
+ assignmentOperators = other.assignmentOperators;
+ nonAssignmentOperators = other.nonAssignmentOperators;
+ preBlockStatements = other.preBlockStatements;
+ preCommandHeaders = other.preCommandHeaders;
+ indentableHeaders = other.indentableHeaders;
+
+ // protected variables
+ // variables set by ASFormatter
+ // must also be updated in activeBeautifierStack
+ inLineNumber = other.inLineNumber;
+ runInIndentContinuation = other.runInIndentContinuation;
+ nonInStatementBrace = other.nonInStatementBrace;
+ objCColonAlignSubsequent = other.objCColonAlignSubsequent;
+ lineCommentNoBeautify = other.lineCommentNoBeautify;
+ isElseHeaderIndent = other.isElseHeaderIndent;
+ isCaseHeaderCommentIndent = other.isCaseHeaderCommentIndent;
+ isNonInStatementArray = other.isNonInStatementArray;
+ isSharpAccessor = other.isSharpAccessor;
+ isSharpDelegate = other.isSharpDelegate;
+ isInExternC = other.isInExternC;
+ isInBeautifySQL = other.isInBeautifySQL;
+ isInIndentableStruct = other.isInIndentableStruct;
+ isInIndentablePreproc = other.isInIndentablePreproc;
+
+ // private variables
+ sourceIterator = other.sourceIterator;
+ currentHeader = other.currentHeader;
+ previousLastLineHeader = other.previousLastLineHeader;
+ probationHeader = other.probationHeader;
+ lastLineHeader = other.lastLineHeader;
+ indentString = other.indentString;
+ verbatimDelimiter = other.verbatimDelimiter;
+ isInQuote = other.isInQuote;
+ isInVerbatimQuote = other.isInVerbatimQuote;
+ haveLineContinuationChar = other.haveLineContinuationChar;
+ isInAsm = other.isInAsm;
+ isInAsmOneLine = other.isInAsmOneLine;
+ isInAsmBlock = other.isInAsmBlock;
+ isInComment = other.isInComment;
+ isInPreprocessorComment = other.isInPreprocessorComment;
+ isInRunInComment = other.isInRunInComment;
+ isInCase = other.isInCase;
+ isInQuestion = other.isInQuestion;
+ isContinuation = other.isContinuation;
+ isInHeader = other.isInHeader;
+ isInTemplate = other.isInTemplate;
+ isInDefine = other.isInDefine;
+ isInDefineDefinition = other.isInDefineDefinition;
+ classIndent = other.classIndent;
+ isIndentModeOff = other.isIndentModeOff;
+ isInClassHeader = other.isInClassHeader;
+ isInClassHeaderTab = other.isInClassHeaderTab;
+ isInClassInitializer = other.isInClassInitializer;
+ isInClass = other.isInClass;
+ isInObjCMethodDefinition = other.isInObjCMethodDefinition;
+ isInObjCMethodCall = other.isInObjCMethodCall;
+ isInObjCMethodCallFirst = other.isInObjCMethodCallFirst;
+ isImmediatelyPostObjCMethodDefinition = other.isImmediatelyPostObjCMethodDefinition;
+ isImmediatelyPostObjCMethodCall = other.isImmediatelyPostObjCMethodCall;
+ isInIndentablePreprocBlock = other.isInIndentablePreprocBlock;
+ isInObjCInterface = other.isInObjCInterface;
+ isInEnum = other.isInEnum;
+ isInEnumTypeID = other.isInEnumTypeID;
+ isInLet = other.isInLet;
+ modifierIndent = other.modifierIndent;
+ switchIndent = other.switchIndent;
+ caseIndent = other.caseIndent;
+ namespaceIndent = other.namespaceIndent;
+ braceIndent = other.braceIndent;
+ braceIndentVtk = other.braceIndentVtk;
+ blockIndent = other.blockIndent;
+ shouldIndentAfterParen = other.shouldIndentAfterParen;
+ labelIndent = other.labelIndent;
+ isInConditional = other.isInConditional;
+ isModeManuallySet = other.isModeManuallySet;
+ shouldForceTabIndentation = other.shouldForceTabIndentation;
+ emptyLineFill = other.emptyLineFill;
+ lineOpensWithLineComment = other.lineOpensWithLineComment;
+ lineOpensWithComment = other.lineOpensWithComment;
+ lineStartsInComment = other.lineStartsInComment;
+ backslashEndsPrevLine = other.backslashEndsPrevLine;
+ blockCommentNoIndent = other.blockCommentNoIndent;
+ blockCommentNoBeautify = other.blockCommentNoBeautify;
+ previousLineProbationTab = other.previousLineProbationTab;
+ lineBeginsWithOpenBrace = other.lineBeginsWithOpenBrace;
+ lineBeginsWithCloseBrace = other.lineBeginsWithCloseBrace;
+ lineBeginsWithComma = other.lineBeginsWithComma;
+ lineIsCommentOnly = other.lineIsCommentOnly;
+ lineIsLineCommentOnly = other.lineIsLineCommentOnly;
+ shouldIndentBracedLine = other.shouldIndentBracedLine;
+ isInSwitch = other.isInSwitch;
+ foundPreCommandHeader = other.foundPreCommandHeader;
+ foundPreCommandMacro = other.foundPreCommandMacro;
+ shouldAlignMethodColon = other.shouldAlignMethodColon;
+ shouldIndentPreprocDefine = other.shouldIndentPreprocDefine;
+ shouldIndentPreprocConditional = other.shouldIndentPreprocConditional;
+ indentCount = other.indentCount;
+ spaceIndentCount = other.spaceIndentCount;
+ spaceIndentObjCMethodAlignment = other.spaceIndentObjCMethodAlignment;
+ bracePosObjCMethodAlignment = other.bracePosObjCMethodAlignment;
+ colonIndentObjCMethodAlignment = other.colonIndentObjCMethodAlignment;
+ lineOpeningBlocksNum = other.lineOpeningBlocksNum;
+ lineClosingBlocksNum = other.lineClosingBlocksNum;
+ fileType = other.fileType;
+ minConditionalOption = other.minConditionalOption;
+ minConditionalIndent = other.minConditionalIndent;
+ parenDepth = other.parenDepth;
+ indentLength = other.indentLength;
+ tabLength = other.tabLength;
+ continuationIndent = other.continuationIndent;
+ blockTabCount = other.blockTabCount;
+ maxContinuationIndent = other.maxContinuationIndent;
+ classInitializerIndents = other.classInitializerIndents;
+ templateDepth = other.templateDepth;
+ squareBracketCount = other.squareBracketCount;
+ prevFinalLineSpaceIndentCount = other.prevFinalLineSpaceIndentCount;
+ prevFinalLineIndentCount = other.prevFinalLineIndentCount;
+ defineIndentCount = other.defineIndentCount;
+ preprocBlockIndent = other.preprocBlockIndent;
+ quoteChar = other.quoteChar;
+ prevNonSpaceCh = other.prevNonSpaceCh;
+ currentNonSpaceCh = other.currentNonSpaceCh;
+ currentNonLegalCh = other.currentNonLegalCh;
+ prevNonLegalCh = other.prevNonLegalCh;
+}
+
+/**
+ * ASBeautifier's destructor
+ */
+ASBeautifier::~ASBeautifier()
+{
+ deleteBeautifierContainer(waitingBeautifierStack);
+ deleteBeautifierContainer(activeBeautifierStack);
+ deleteContainer(waitingBeautifierStackLengthStack);
+ deleteContainer(activeBeautifierStackLengthStack);
+ deleteContainer(headerStack);
+ deleteTempStacksContainer(tempStacks);
+ deleteContainer(squareBracketDepthStack);
+ deleteContainer(blockStatementStack);
+ deleteContainer(parenStatementStack);
+ deleteContainer(braceBlockStateStack);
+ deleteContainer(continuationIndentStack);
+ deleteContainer(continuationIndentStackSizeStack);
+ deleteContainer(parenIndentStack);
+ deleteContainer(preprocIndentStack);
+}
+
+/**
+ * initialize the ASBeautifier.
+ *
+ * This init() should be called every time a ABeautifier object is to start
+ * beautifying a NEW source file.
+ * It is called only when a new ASFormatter object is created.
+ * init() receives a pointer to a ASSourceIterator object that will be
+ * used to iterate through the source code.
+ *
+ * @param iter a pointer to the ASSourceIterator or ASStreamIterator object.
+ */
+void ASBeautifier::init(ASSourceIterator* iter)
+{
+ sourceIterator = iter;
+ initVectors();
+ ASBase::init(getFileType());
+ g_preprocessorCppExternCBrace = 0;
+
+ initContainer(waitingBeautifierStack, new vector<ASBeautifier*>);
+ initContainer(activeBeautifierStack, new vector<ASBeautifier*>);
+
+ initContainer(waitingBeautifierStackLengthStack, new vector<int>);
+ initContainer(activeBeautifierStackLengthStack, new vector<int>);
+
+ initContainer(headerStack, new vector<const string*>);
+
+ initTempStacksContainer(tempStacks, new vector<vector<const string*>*>);
+ tempStacks->emplace_back(new vector<const string*>);
+
+ initContainer(squareBracketDepthStack, new vector<int>);
+ initContainer(blockStatementStack, new vector<bool>);
+ initContainer(parenStatementStack, new vector<bool>);
+ initContainer(braceBlockStateStack, new vector<bool>);
+ braceBlockStateStack->push_back(true);
+ initContainer(continuationIndentStack, new vector<int>);
+ initContainer(continuationIndentStackSizeStack, new vector<int>);
+ continuationIndentStackSizeStack->emplace_back(0);
+ initContainer(parenIndentStack, new vector<int>);
+ initContainer(preprocIndentStack, new vector<pair<int, int> >);
+
+ previousLastLineHeader = nullptr;
+ currentHeader = nullptr;
+
+ isInQuote = false;
+ isInVerbatimQuote = false;
+ haveLineContinuationChar = false;
+ isInAsm = false;
+ isInAsmOneLine = false;
+ isInAsmBlock = false;
+ isInComment = false;
+ isInPreprocessorComment = false;
+ isInRunInComment = false;
+ isContinuation = false;
+ isInCase = false;
+ isInQuestion = false;
+ isIndentModeOff = false;
+ isInClassHeader = false;
+ isInClassHeaderTab = false;
+ isInClassInitializer = false;
+ isInClass = false;
+ isInObjCMethodDefinition = false;
+ isInObjCMethodCall = false;
+ isInObjCMethodCallFirst = false;
+ isImmediatelyPostObjCMethodDefinition = false;
+ isImmediatelyPostObjCMethodCall = false;
+ isInIndentablePreprocBlock = false;
+ isInObjCInterface = false;
+ isInEnum = false;
+ isInEnumTypeID = false;
+ isInLet = false;
+ isInHeader = false;
+ isInTemplate = false;
+ isInConditional = false;
+
+ indentCount = 0;
+ spaceIndentCount = 0;
+ spaceIndentObjCMethodAlignment = 0;
+ bracePosObjCMethodAlignment = 0;
+ colonIndentObjCMethodAlignment = 0;
+ lineOpeningBlocksNum = 0;
+ lineClosingBlocksNum = 0;
+ templateDepth = 0;
+ squareBracketCount = 0;
+ parenDepth = 0;
+ blockTabCount = 0;
+ prevFinalLineSpaceIndentCount = 0;
+ prevFinalLineIndentCount = 0;
+ defineIndentCount = 0;
+ preprocBlockIndent = 0;
+ prevNonSpaceCh = '{';
+ currentNonSpaceCh = '{';
+ prevNonLegalCh = '{';
+ currentNonLegalCh = '{';
+ quoteChar = ' ';
+ probationHeader = nullptr;
+ lastLineHeader = nullptr;
+ backslashEndsPrevLine = false;
+ lineOpensWithLineComment = false;
+ lineOpensWithComment = false;
+ lineStartsInComment = false;
+ isInDefine = false;
+ isInDefineDefinition = false;
+ lineCommentNoBeautify = false;
+ isElseHeaderIndent = false;
+ isCaseHeaderCommentIndent = false;
+ blockCommentNoIndent = false;
+ blockCommentNoBeautify = false;
+ previousLineProbationTab = false;
+ lineBeginsWithOpenBrace = false;
+ lineBeginsWithCloseBrace = false;
+ lineBeginsWithComma = false;
+ lineIsCommentOnly = false;
+ lineIsLineCommentOnly = false;
+ shouldIndentBracedLine = true;
+ isInSwitch = false;
+ foundPreCommandHeader = false;
+ foundPreCommandMacro = false;
+
+ isNonInStatementArray = false;
+ isSharpAccessor = false;
+ isSharpDelegate = false;
+ isInExternC = false;
+ isInBeautifySQL = false;
+ isInIndentableStruct = false;
+ isInIndentablePreproc = false;
+ inLineNumber = 0;
+ runInIndentContinuation = 0;
+ nonInStatementBrace = 0;
+ objCColonAlignSubsequent = 0;
+}
+
+/*
+ * initialize the vectors
+ */
+void ASBeautifier::initVectors()
+{
+ if (fileType == beautifierFileType) // don't build unless necessary
+ return;
+
+ beautifierFileType = fileType;
+
+ headers->clear();
+ nonParenHeaders->clear();
+ assignmentOperators->clear();
+ nonAssignmentOperators->clear();
+ preBlockStatements->clear();
+ preCommandHeaders->clear();
+ indentableHeaders->clear();
+
+ ASResource::buildHeaders(headers, fileType, true);
+ ASResource::buildNonParenHeaders(nonParenHeaders, fileType, true);
+ ASResource::buildAssignmentOperators(assignmentOperators);
+ ASResource::buildNonAssignmentOperators(nonAssignmentOperators);
+ ASResource::buildPreBlockStatements(preBlockStatements, fileType);
+ ASResource::buildPreCommandHeaders(preCommandHeaders, fileType);
+ ASResource::buildIndentableHeaders(indentableHeaders);
+}
+
+/**
+ * set indentation style to C/C++.
+ */
+void ASBeautifier::setCStyle()
+{
+ fileType = C_TYPE;
+}
+
+/**
+ * set indentation style to Java.
+ */
+void ASBeautifier::setJavaStyle()
+{
+ fileType = JAVA_TYPE;
+}
+
+/**
+ * set indentation style to C#.
+ */
+void ASBeautifier::setSharpStyle()
+{
+ fileType = SHARP_TYPE;
+}
+
+/**
+ * set mode manually set flag
+ */
+void ASBeautifier::setModeManuallySet(bool state)
+{
+ isModeManuallySet = state;
+}
+
+/**
+ * set tabLength equal to indentLength.
+ * This is done when tabLength is not explicitly set by
+ * "indent=force-tab-x"
+ *
+ */
+void ASBeautifier::setDefaultTabLength()
+{
+ tabLength = indentLength;
+}
+
+/**
+ * indent using a different tab setting for indent=force-tab
+ *
+ * @param length number of spaces per tab.
+ */
+void ASBeautifier::setForceTabXIndentation(int length)
+{
+ // set tabLength instead of indentLength
+ indentString = "\t";
+ tabLength = length;
+ shouldForceTabIndentation = true;
+}
+
+/**
+ * indent using one tab per indentation
+ */
+void ASBeautifier::setTabIndentation(int length, bool forceTabs)
+{
+ indentString = "\t";
+ indentLength = length;
+ shouldForceTabIndentation = forceTabs;
+}
+
+/**
+ * indent using a number of spaces per indentation.
+ *
+ * @param length number of spaces per indent.
+ */
+void ASBeautifier::setSpaceIndentation(int length)
+{
+ indentString = string(length, ' ');
+ indentLength = length;
+}
+
+/**
+* indent continuation lines using a number of indents.
+*
+* @param indent number of indents per line.
+*/
+void ASBeautifier::setContinuationIndentation(int indent)
+{
+ continuationIndent = indent;
+}
+
+/**
+ * set the maximum indentation between two lines in a multi-line statement.
+ *
+ * @param max maximum indentation length.
+ */
+void ASBeautifier::setMaxContinuationIndentLength(int max)
+{
+ maxContinuationIndent = max;
+}
+
+// retained for compatability with release 2.06
+// "MaxInStatementIndent" has been changed to "MaxContinuationIndent" in 3.0
+// it is referenced only by the old "MaxInStatementIndent" options
+void ASBeautifier::setMaxInStatementIndentLength(int max)
+{
+ setMaxContinuationIndentLength(max);
+}
+
+/**
+ * set the minimum conditional indentation option.
+ *
+ * @param min minimal indentation option.
+ */
+void ASBeautifier::setMinConditionalIndentOption(int min)
+{
+ minConditionalOption = min;
+}
+
+/**
+ * set minConditionalIndent from the minConditionalOption.
+ */
+void ASBeautifier::setMinConditionalIndentLength()
+{
+ if (minConditionalOption == MINCOND_ZERO)
+ minConditionalIndent = 0;
+ else if (minConditionalOption == MINCOND_ONE)
+ minConditionalIndent = indentLength;
+ else if (minConditionalOption == MINCOND_ONEHALF)
+ minConditionalIndent = indentLength / 2;
+ // minConditionalOption = INDENT_TWO
+ else
+ minConditionalIndent = indentLength * 2;
+}
+
+/**
+ * set the state of the brace indent option. If true, braces will
+ * be indented one additional indent.
+ *
+ * @param state state of option.
+ */
+void ASBeautifier::setBraceIndent(bool state)
+{
+ braceIndent = state;
+}
+
+/**
+* set the state of the brace indent VTK option. If true, braces will
+* be indented one additional indent, except for the opening brace.
+*
+* @param state state of option.
+*/
+void ASBeautifier::setBraceIndentVtk(bool state)
+{
+ // need to set both of these
+ setBraceIndent(state);
+ braceIndentVtk = state;
+}
+
+/**
+ * set the state of the block indentation option. If true, entire blocks
+ * will be indented one additional indent, similar to the GNU indent style.
+ *
+ * @param state state of option.
+ */
+void ASBeautifier::setBlockIndent(bool state)
+{
+ blockIndent = state;
+}
+
+/**
+ * set the state of the class indentation option. If true, C++ class
+ * definitions will be indented one additional indent.
+ *
+ * @param state state of option.
+ */
+void ASBeautifier::setClassIndent(bool state)
+{
+ classIndent = state;
+}
+
+/**
+ * set the state of the modifier indentation option. If true, C++ class
+ * access modifiers will be indented one-half an indent.
+ *
+ * @param state state of option.
+ */
+void ASBeautifier::setModifierIndent(bool state)
+{
+ modifierIndent = state;
+}
+
+/**
+ * set the state of the switch indentation option. If true, blocks of 'switch'
+ * statements will be indented one additional indent.
+ *
+ * @param state state of option.
+ */
+void ASBeautifier::setSwitchIndent(bool state)
+{
+ switchIndent = state;
+}
+
+/**
+ * set the state of the case indentation option. If true, lines of 'case'
+ * statements will be indented one additional indent.
+ *
+ * @param state state of option.
+ */
+void ASBeautifier::setCaseIndent(bool state)
+{
+ caseIndent = state;
+}
+
+/**
+ * set the state of the namespace indentation option.
+ * If true, blocks of 'namespace' statements will be indented one
+ * additional indent. Otherwise, NO indentation will be added.
+ *
+ * @param state state of option.
+ */
+void ASBeautifier::setNamespaceIndent(bool state)
+{
+ namespaceIndent = state;
+}
+
+/**
+* set the state of the indent after parens option.
+*
+* @param state state of option.
+*/
+void ASBeautifier::setAfterParenIndent(bool state)
+{
+ shouldIndentAfterParen = state;
+}
+
+/**
+ * set the state of the label indentation option.
+ * If true, labels will be indented one indent LESS than the
+ * current indentation level.
+ * If false, labels will be flushed to the left with NO
+ * indent at all.
+ *
+ * @param state state of option.
+ */
+void ASBeautifier::setLabelIndent(bool state)
+{
+ labelIndent = state;
+}
+
+/**
+ * set the state of the preprocessor indentation option.
+ * If true, multi-line #define statements will be indented.
+ *
+ * @param state state of option.
+ */
+void ASBeautifier::setPreprocDefineIndent(bool state)
+{
+ shouldIndentPreprocDefine = state;
+}
+
+void ASBeautifier::setPreprocConditionalIndent(bool state)
+{
+ shouldIndentPreprocConditional = state;
+}
+
+/**
+ * set the state of the empty line fill option.
+ * If true, empty lines will be filled with the whitespace.
+ * of their previous lines.
+ * If false, these lines will remain empty.
+ *
+ * @param state state of option.
+ */
+void ASBeautifier::setEmptyLineFill(bool state)
+{
+ emptyLineFill = state;
+}
+
+void ASBeautifier::setAlignMethodColon(bool state)
+{
+ shouldAlignMethodColon = state;
+}
+
+/**
+ * get the file type.
+ */
+int ASBeautifier::getFileType() const
+{
+ return fileType;
+}
+
+/**
+ * get the number of spaces per indent
+ *
+ * @return value of indentLength option.
+ */
+int ASBeautifier::getIndentLength() const
+{
+ return indentLength;
+}
+
+/**
+ * get the char used for indentation, space or tab
+ *
+ * @return the char used for indentation.
+ */
+string ASBeautifier::getIndentString() const
+{
+ return indentString;
+}
+
+/**
+ * get mode manually set flag
+ */
+bool ASBeautifier::getModeManuallySet() const
+{
+ return isModeManuallySet;
+}
+
+/**
+ * get the state of the force tab indentation option.
+ *
+ * @return state of force tab indentation.
+ */
+bool ASBeautifier::getForceTabIndentation() const
+{
+ return shouldForceTabIndentation;
+}
+
+/**
+* Get the state of the Objective-C align method colon option.
+*
+* @return state of shouldAlignMethodColon option.
+*/
+bool ASBeautifier::getAlignMethodColon() const
+{
+ return shouldAlignMethodColon;
+}
+
+/**
+ * get the state of the block indentation option.
+ *
+ * @return state of blockIndent option.
+ */
+bool ASBeautifier::getBlockIndent() const
+{
+ return blockIndent;
+}
+
+/**
+ * get the state of the brace indentation option.
+ *
+ * @return state of braceIndent option.
+ */
+bool ASBeautifier::getBraceIndent() const
+{
+ return braceIndent;
+}
+
+/**
+* Get the state of the namespace indentation option. If true, blocks
+* of the 'namespace' statement will be indented one additional indent.
+*
+* @return state of namespaceIndent option.
+*/
+bool ASBeautifier::getNamespaceIndent() const
+{
+ return namespaceIndent;
+}
+
+/**
+ * Get the state of the class indentation option. If true, blocks of
+ * the 'class' statement will be indented one additional indent.
+ *
+ * @return state of classIndent option.
+ */
+bool ASBeautifier::getClassIndent() const
+{
+ return classIndent;
+}
+
+/**
+ * Get the state of the class access modifier indentation option.
+ * If true, the class access modifiers will be indented one-half indent.
+ *
+ * @return state of modifierIndent option.
+ */
+bool ASBeautifier::getModifierIndent() const
+{
+ return modifierIndent;
+}
+
+/**
+ * get the state of the switch indentation option. If true, blocks of
+ * the 'switch' statement will be indented one additional indent.
+ *
+ * @return state of switchIndent option.
+ */
+bool ASBeautifier::getSwitchIndent() const
+{
+ return switchIndent;
+}
+
+/**
+ * get the state of the case indentation option. If true, lines of 'case'
+ * statements will be indented one additional indent.
+ *
+ * @return state of caseIndent option.
+ */
+bool ASBeautifier::getCaseIndent() const
+{
+ return caseIndent;
+}
+
+/**
+ * get the state of the empty line fill option.
+ * If true, empty lines will be filled with the whitespace.
+ * of their previous lines.
+ * If false, these lines will remain empty.
+ *
+ * @return state of emptyLineFill option.
+ */
+bool ASBeautifier::getEmptyLineFill() const
+{
+ return emptyLineFill;
+}
+
+/**
+ * get the state of the preprocessor indentation option.
+ * If true, preprocessor "define" lines will be indented.
+ * If false, preprocessor "define" lines will be unchanged.
+ *
+ * @return state of shouldIndentPreprocDefine option.
+ */
+bool ASBeautifier::getPreprocDefineIndent() const
+{
+ return shouldIndentPreprocDefine;
+}
+
+/**
+ * get the length of the tab indentation option.
+ *
+ * @return length of tab indent option.
+ */
+int ASBeautifier::getTabLength() const
+{
+ return tabLength;
+}
+
+/**
+ * beautify a line of source code.
+ * every line of source code in a source code file should be sent
+ * one after the other to the beautify method.
+ *
+ * @return the indented line.
+ * @param originalLine the original unindented line.
+ */
+string ASBeautifier::beautify(const string& originalLine)
+{
+ string line;
+ bool isInQuoteContinuation = isInVerbatimQuote || haveLineContinuationChar;
+
+ currentHeader = nullptr;
+ lastLineHeader = nullptr;
+ blockCommentNoBeautify = blockCommentNoIndent;
+ isInClass = false;
+ isInSwitch = false;
+ lineBeginsWithOpenBrace = false;
+ lineBeginsWithCloseBrace = false;
+ lineBeginsWithComma = false;
+ lineIsCommentOnly = false;
+ lineIsLineCommentOnly = false;
+ shouldIndentBracedLine = true;
+ isInAsmOneLine = false;
+ lineOpensWithLineComment = false;
+ lineOpensWithComment = false;
+ lineStartsInComment = isInComment;
+ previousLineProbationTab = false;
+ lineOpeningBlocksNum = 0;
+ lineClosingBlocksNum = 0;
+ if (isImmediatelyPostObjCMethodDefinition)
+ clearObjCMethodDefinitionAlignment();
+ if (isImmediatelyPostObjCMethodCall)
+ {
+ isImmediatelyPostObjCMethodCall = false;
+ isInObjCMethodCall = false;
+ objCColonAlignSubsequent = 0;
+ }
+
+ // handle and remove white spaces around the line:
+ // If not in comment, first find out size of white space before line,
+ // so that possible comments starting in the line continue in
+ // relation to the preliminary white-space.
+ if (isInQuoteContinuation)
+ {
+ // trim a single space added by ASFormatter, otherwise leave it alone
+ if (!(originalLine.length() == 1 && originalLine[0] == ' '))
+ line = originalLine;
+ }
+ else if (isInComment || isInBeautifySQL)
+ {
+ // trim the end of comment and SQL lines
+ line = originalLine;
+ size_t trimEnd = line.find_last_not_of(" \t");
+ if (trimEnd == string::npos)
+ trimEnd = 0;
+ else
+ trimEnd++;
+ if (trimEnd < line.length())
+ line.erase(trimEnd);
+ // does a brace open the line
+ size_t firstChar = line.find_first_not_of(" \t");
+ if (firstChar != string::npos)
+ {
+ if (line[firstChar] == '{')
+ lineBeginsWithOpenBrace = true;
+ else if (line[firstChar] == '}')
+ lineBeginsWithCloseBrace = true;
+ else if (line[firstChar] == ',')
+ lineBeginsWithComma = true;
+ }
+ }
+ else
+ {
+ line = trim(originalLine);
+ if (line.length() > 0)
+ {
+ if (line[0] == '{')
+ lineBeginsWithOpenBrace = true;
+ else if (line[0] == '}')
+ lineBeginsWithCloseBrace = true;
+ else if (line[0] == ',')
+ lineBeginsWithComma = true;
+ else if (line.compare(0, 2, "//") == 0)
+ lineIsLineCommentOnly = true;
+ else if (line.compare(0, 2, "/*") == 0)
+ {
+ if (line.find("*/", 2) != string::npos)
+ lineIsCommentOnly = true;
+ }
+ }
+
+ isInRunInComment = false;
+ size_t j = line.find_first_not_of(" \t{");
+ if (j != string::npos && line.compare(j, 2, "//") == 0)
+ lineOpensWithLineComment = true;
+ if (j != string::npos && line.compare(j, 2, "/*") == 0)
+ {
+ lineOpensWithComment = true;
+ size_t k = line.find_first_not_of(" \t");
+ if (k != string::npos && line.compare(k, 1, "{") == 0)
+ isInRunInComment = true;
+ }
+ }
+
+ // When indent is OFF the lines must still be processed by ASBeautifier.
+ // Otherwise the lines immediately following may not be indented correctly.
+ if ((lineIsLineCommentOnly || lineIsCommentOnly)
+ && line.find("*INDENT-OFF*", 0) != string::npos)
+ isIndentModeOff = true;
+
+ if (line.length() == 0)
+ {
+ if (backslashEndsPrevLine)
+ {
+ backslashEndsPrevLine = false;
+ // check if this line ends a multi-line #define
+ // if so, remove the #define's cloned beautifier from the active
+ // beautifier stack and delete it.
+ if (isInDefineDefinition && !isInDefine)
+ {
+ isInDefineDefinition = false;
+ ASBeautifier* defineBeautifier = activeBeautifierStack->back();
+ activeBeautifierStack->pop_back();
+ delete defineBeautifier;
+ }
+ }
+ if (emptyLineFill && !isInQuoteContinuation)
+ {
+ if (isInIndentablePreprocBlock)
+ return preLineWS(preprocBlockIndent, 0);
+ if (!headerStack->empty() || isInEnum)
+ return preLineWS(prevFinalLineIndentCount, prevFinalLineSpaceIndentCount);
+ // must fall thru here
+ }
+ else
+ return line;
+ }
+
+ // handle preprocessor commands
+ if (isInIndentablePreprocBlock
+ && line.length() > 0
+ && line[0] != '#')
+ {
+ string indentedLine;
+ if (isInClassHeaderTab || isInClassInitializer)
+ {
+ // parsing is turned off in ASFormatter by indent-off
+ // the originalLine will probably never be returned here
+ indentedLine = preLineWS(prevFinalLineIndentCount, prevFinalLineSpaceIndentCount) + line;
+ return getIndentedLineReturn(indentedLine, originalLine);
+ }
+ indentedLine = preLineWS(preprocBlockIndent, 0) + line;
+ return getIndentedLineReturn(indentedLine, originalLine);
+ }
+
+ if (!isInComment
+ && !isInQuoteContinuation
+ && line.length() > 0
+ && ((line[0] == '#' && !isIndentedPreprocessor(line, 0))
+ || backslashEndsPrevLine))
+ {
+ if (line[0] == '#' && !isInDefine)
+ {
+ string preproc = extractPreprocessorStatement(line);
+ processPreprocessor(preproc, line);
+ if (isInIndentablePreprocBlock || isInIndentablePreproc)
+ {
+ string indentedLine;
+ if ((preproc.length() >= 2 && preproc.substr(0, 2) == "if")) // #if, #ifdef, #ifndef
+ {
+ indentedLine = preLineWS(preprocBlockIndent, 0) + line;
+ preprocBlockIndent += 1;
+ isInIndentablePreprocBlock = true;
+ }
+ else if (preproc == "else" || preproc == "elif")
+ {
+ indentedLine = preLineWS(preprocBlockIndent - 1, 0) + line;
+ }
+ else if (preproc == "endif")
+ {
+ preprocBlockIndent -= 1;
+ indentedLine = preLineWS(preprocBlockIndent, 0) + line;
+ if (preprocBlockIndent == 0)
+ isInIndentablePreprocBlock = false;
+ }
+ else
+ indentedLine = preLineWS(preprocBlockIndent, 0) + line;
+ return getIndentedLineReturn(indentedLine, originalLine);
+ }
+ if (shouldIndentPreprocConditional && preproc.length() > 0)
+ {
+ string indentedLine;
+ if (preproc.length() >= 2 && preproc.substr(0, 2) == "if") // #if, #ifdef, #ifndef
+ {
+ pair<int, int> entry; // indentCount, spaceIndentCount
+ if (!isInDefine && activeBeautifierStack != nullptr && !activeBeautifierStack->empty())
+ entry = activeBeautifierStack->back()->computePreprocessorIndent();
+ else
+ entry = computePreprocessorIndent();
+ preprocIndentStack->emplace_back(entry);
+ indentedLine = preLineWS(preprocIndentStack->back().first,
+ preprocIndentStack->back().second) + line;
+ return getIndentedLineReturn(indentedLine, originalLine);
+ }
+ if (preproc == "else" || preproc == "elif")
+ {
+ if (!preprocIndentStack->empty()) // if no entry don't indent
+ {
+ indentedLine = preLineWS(preprocIndentStack->back().first,
+ preprocIndentStack->back().second) + line;
+ return getIndentedLineReturn(indentedLine, originalLine);
+ }
+ }
+ else if (preproc == "endif")
+ {
+ if (!preprocIndentStack->empty()) // if no entry don't indent
+ {
+ indentedLine = preLineWS(preprocIndentStack->back().first,
+ preprocIndentStack->back().second) + line;
+ preprocIndentStack->pop_back();
+ return getIndentedLineReturn(indentedLine, originalLine);
+ }
+ }
+ }
+ }
+
+ // check if the last char is a backslash
+ if (line.length() > 0)
+ backslashEndsPrevLine = (line[line.length() - 1] == '\\');
+ // comments within the definition line can be continued without the backslash
+ if (isInPreprocessorUnterminatedComment(line))
+ backslashEndsPrevLine = true;
+
+ // check if this line ends a multi-line #define
+ // if so, use the #define's cloned beautifier for the line's indentation
+ // and then remove it from the active beautifier stack and delete it.
+ if (!backslashEndsPrevLine && isInDefineDefinition && !isInDefine)
+ {
+ isInDefineDefinition = false;
+ ASBeautifier* defineBeautifier = activeBeautifierStack->back();
+ activeBeautifierStack->pop_back();
+
+ string indentedLine = defineBeautifier->beautify(line);
+ delete defineBeautifier;
+ return getIndentedLineReturn(indentedLine, originalLine);
+ }
+
+ // unless this is a multi-line #define, return this precompiler line as is.
+ if (!isInDefine && !isInDefineDefinition)
+ return originalLine;
+ }
+
+ // if there exists any worker beautifier in the activeBeautifierStack,
+ // then use it instead of me to indent the current line.
+ // variables set by ASFormatter must be updated.
+ if (!isInDefine && activeBeautifierStack != nullptr && !activeBeautifierStack->empty())
+ {
+ activeBeautifierStack->back()->inLineNumber = inLineNumber;
+ activeBeautifierStack->back()->runInIndentContinuation = runInIndentContinuation;
+ activeBeautifierStack->back()->nonInStatementBrace = nonInStatementBrace;
+ activeBeautifierStack->back()->objCColonAlignSubsequent = objCColonAlignSubsequent;
+ activeBeautifierStack->back()->lineCommentNoBeautify = lineCommentNoBeautify;
+ activeBeautifierStack->back()->isElseHeaderIndent = isElseHeaderIndent;
+ activeBeautifierStack->back()->isCaseHeaderCommentIndent = isCaseHeaderCommentIndent;
+ activeBeautifierStack->back()->isNonInStatementArray = isNonInStatementArray;
+ activeBeautifierStack->back()->isSharpAccessor = isSharpAccessor;
+ activeBeautifierStack->back()->isSharpDelegate = isSharpDelegate;
+ activeBeautifierStack->back()->isInExternC = isInExternC;
+ activeBeautifierStack->back()->isInBeautifySQL = isInBeautifySQL;
+ activeBeautifierStack->back()->isInIndentableStruct = isInIndentableStruct;
+ activeBeautifierStack->back()->isInIndentablePreproc = isInIndentablePreproc;
+ // must return originalLine not the trimmed line
+ return activeBeautifierStack->back()->beautify(originalLine);
+ }
+
+ // Flag an indented header in case this line is a one-line block.
+ // The header in the header stack will be deleted by a one-line block.
+ bool isInExtraHeaderIndent = false;
+ if (!headerStack->empty()
+ && lineBeginsWithOpenBrace
+ && (headerStack->back() != &AS_OPEN_BRACE
+ || probationHeader != nullptr))
+ isInExtraHeaderIndent = true;
+
+ size_t iPrelim = headerStack->size();
+
+ // calculate preliminary indentation based on headerStack and data from past lines
+ computePreliminaryIndentation();
+
+ // parse characters in the current line.
+ parseCurrentLine(line);
+
+ // handle special cases of indentation
+ adjustParsedLineIndentation(iPrelim, isInExtraHeaderIndent);
+
+ if (isInObjCMethodDefinition)
+ adjustObjCMethodDefinitionIndentation(line);
+
+ if (isInObjCMethodCall)
+ adjustObjCMethodCallIndentation(line);
+
+ if (isInDefine)
+ {
+ if (line.length() > 0 && line[0] == '#')
+ {
+ // the 'define' does not have to be attached to the '#'
+ string preproc = trim(line.substr(1));
+ if (preproc.compare(0, 6, "define") == 0)
+ {
+ if (!continuationIndentStack->empty()
+ && continuationIndentStack->back() > 0)
+ {
+ defineIndentCount = indentCount;
+ }
+ else
+ {
+ defineIndentCount = indentCount - 1;
+ --indentCount;
+ }
+ }
+ }
+
+ indentCount -= defineIndentCount;
+ }
+
+ if (indentCount < 0)
+ indentCount = 0;
+
+ if (lineCommentNoBeautify || blockCommentNoBeautify || isInQuoteContinuation)
+ indentCount = spaceIndentCount = 0;
+
+ // finally, insert indentations into beginning of line
+
+ string indentedLine = preLineWS(indentCount, spaceIndentCount) + line;
+ indentedLine = getIndentedLineReturn(indentedLine, originalLine);
+
+ prevFinalLineSpaceIndentCount = spaceIndentCount;
+ prevFinalLineIndentCount = indentCount;
+
+ if (lastLineHeader != nullptr)
+ previousLastLineHeader = lastLineHeader;
+
+ if ((lineIsLineCommentOnly || lineIsCommentOnly)
+ && line.find("*INDENT-ON*", 0) != string::npos)
+ isIndentModeOff = false;
+
+ return indentedLine;
+}
+
+const string& ASBeautifier::getIndentedLineReturn(const string& newLine, const string& originalLine) const
+{
+ if (isIndentModeOff)
+ return originalLine;
+ return newLine;
+}
+
+string ASBeautifier::preLineWS(int lineIndentCount, int lineSpaceIndentCount) const
+{
+ if (shouldForceTabIndentation)
+ {
+ if (tabLength != indentLength)
+ {
+ // adjust for different tab length
+ int indentCountOrig = lineIndentCount;
+ int spaceIndentCountOrig = lineSpaceIndentCount;
+ lineIndentCount = ((indentCountOrig * indentLength) + spaceIndentCountOrig) / tabLength;
+ lineSpaceIndentCount = ((indentCountOrig * indentLength) + spaceIndentCountOrig) % tabLength;
+ }
+ else
+ {
+ lineIndentCount += lineSpaceIndentCount / indentLength;
+ lineSpaceIndentCount = lineSpaceIndentCount % indentLength;
+ }
+ }
+
+ string ws;
+ for (int i = 0; i < lineIndentCount; i++)
+ ws += indentString;
+ while ((lineSpaceIndentCount--) > 0)
+ ws += string(" ");
+ return ws;
+}
+
+/**
+ * register a continuation indent.
+ */
+void ASBeautifier::registerContinuationIndent(const string& line, int i, int spaceIndentCount_,
+ int tabIncrementIn, int minIndent, bool updateParenStack)
+{
+ int remainingCharNum = line.length() - i;
+ int nextNonWSChar = getNextProgramCharDistance(line, i);
+
+ // if indent is around the last char in the line OR indent-after-paren is requested,
+ // indent with the continuation indent
+ if (nextNonWSChar == remainingCharNum || shouldIndentAfterParen)
+ {
+ int previousIndent = spaceIndentCount_;
+ if (!continuationIndentStack->empty())
+ previousIndent = continuationIndentStack->back();
+ int currIndent = continuationIndent * indentLength + previousIndent;
+ if (currIndent > maxContinuationIndent && line[i] != '{')
+ currIndent = indentLength * 2 + spaceIndentCount_;
+ continuationIndentStack->emplace_back(currIndent);
+ if (updateParenStack)
+ parenIndentStack->emplace_back(previousIndent);
+ return;
+ }
+
+ if (updateParenStack)
+ parenIndentStack->emplace_back(i + spaceIndentCount_ - runInIndentContinuation);
+
+ int tabIncrement = tabIncrementIn;
+
+ // check for following tabs
+ for (int j = i + 1; j < (i + nextNonWSChar); j++)
+ {
+ if (line[j] == '\t')
+ tabIncrement += convertTabToSpaces(j, tabIncrement);
+ }
+
+ int continuationIndentCount = i + nextNonWSChar + spaceIndentCount_ + tabIncrement;
+
+ // check for run-in statement
+ if (i > 0 && line[0] == '{')
+ continuationIndentCount -= indentLength;
+
+ if (continuationIndentCount < minIndent)
+ continuationIndentCount = minIndent + spaceIndentCount_;
+
+ // this is not done for an in-statement array
+ if (continuationIndentCount > maxContinuationIndent
+ && !(prevNonLegalCh == '=' && currentNonLegalCh == '{'))
+ continuationIndentCount = indentLength * 2 + spaceIndentCount_;
+
+ if (!continuationIndentStack->empty()
+ && continuationIndentCount < continuationIndentStack->back())
+ continuationIndentCount = continuationIndentStack->back();
+
+ // the block opener is not indented for a NonInStatementArray
+ if ((isNonInStatementArray && line[i] == '{')
+ && !isInEnum && !braceBlockStateStack->empty() && braceBlockStateStack->back())
+ continuationIndentCount = 0;
+
+ continuationIndentStack->emplace_back(continuationIndentCount);
+}
+
+/**
+* Register a continuation indent for a class header or a class initializer colon.
+*/
+void ASBeautifier::registerContinuationIndentColon(const string& line, int i, int tabIncrementIn)
+{
+ assert(line[i] == ':');
+ assert(isInClassInitializer || isInClassHeaderTab);
+
+ // register indent at first word after the colon
+ size_t firstChar = line.find_first_not_of(" \t");
+ if (firstChar == (size_t) i) // firstChar is ':'
+ {
+ size_t firstWord = line.find_first_not_of(" \t", firstChar + 1);
+ if (firstChar != string::npos)
+ {
+ int continuationIndentCount = firstWord + spaceIndentCount + tabIncrementIn;
+ continuationIndentStack->emplace_back(continuationIndentCount);
+ isContinuation = true;
+ }
+ }
+}
+
+/**
+ * Compute indentation for a preprocessor #if statement.
+ * This may be called for the activeBeautiferStack
+ * instead of the active ASBeautifier object.
+ */
+pair<int, int> ASBeautifier::computePreprocessorIndent()
+{
+ computePreliminaryIndentation();
+ pair<int, int> entry(indentCount, spaceIndentCount);
+ if (!headerStack->empty()
+ && entry.first > 0
+ && (headerStack->back() == &AS_IF
+ || headerStack->back() == &AS_ELSE
+ || headerStack->back() == &AS_FOR
+ || headerStack->back() == &AS_WHILE))
+ --entry.first;
+ return entry;
+}
+
+/**
+ * get distance to the next non-white space, non-comment character in the line.
+ * if no such character exists, return the length remaining to the end of the line.
+ */
+int ASBeautifier::getNextProgramCharDistance(const string& line, int i) const
+{
+ bool inComment = false;
+ int remainingCharNum = line.length() - i;
+ int charDistance;
+ char ch;
+
+ for (charDistance = 1; charDistance < remainingCharNum; charDistance++)
+ {
+ ch = line[i + charDistance];
+ if (inComment)
+ {
+ if (line.compare(i + charDistance, 2, "*/") == 0)
+ {
+ charDistance++;
+ inComment = false;
+ }
+ continue;
+ }
+ else if (isWhiteSpace(ch))
+ continue;
+ else if (ch == '/')
+ {
+ if (line.compare(i + charDistance, 2, "//") == 0)
+ return remainingCharNum;
+ if (line.compare(i + charDistance, 2, "/*") == 0)
+ {
+ charDistance++;
+ inComment = true;
+ }
+ }
+ else
+ return charDistance;
+ }
+
+ return charDistance;
+}
+
+/**
+ * find the index number of a string element in a container of strings
+ *
+ * @return the index number of element in the container. -1 if element not found.
+ * @param container a vector of strings.
+ * @param element the element to find .
+ */
+int ASBeautifier::indexOf(const vector<const string*>& container, const string* element) const
+{
+ vector<const string*>::const_iterator where;
+
+ where = find(container.begin(), container.end(), element);
+ if (where == container.end())
+ return -1;
+ return (int) (where - container.begin());
+}
+
+/**
+ * convert tabs to spaces.
+ * i is the position of the character to convert to spaces.
+ * tabIncrementIn is the increment that must be added for tab indent characters
+ * to get the correct column for the current tab.
+ */
+int ASBeautifier::convertTabToSpaces(int i, int tabIncrementIn) const
+{
+ int tabToSpacesAdjustment = indentLength - 1 - ((tabIncrementIn + i) % indentLength);
+ return tabToSpacesAdjustment;
+}
+
+/**
+ * trim removes the white space surrounding a line.
+ *
+ * @return the trimmed line.
+ * @param str the line to trim.
+ */
+string ASBeautifier::trim(const string& str) const
+{
+ int start = 0;
+ int end = str.length() - 1;
+
+ while (start < end && isWhiteSpace(str[start]))
+ start++;
+
+ while (start <= end && isWhiteSpace(str[end]))
+ end--;
+
+ // don't trim if it ends in a continuation
+ if (end > -1 && str[end] == '\\')
+ end = str.length() - 1;
+
+ string returnStr(str, start, end + 1 - start);
+ return returnStr;
+}
+
+/**
+ * rtrim removes the white space from the end of a line.
+ *
+ * @return the trimmed line.
+ * @param str the line to trim.
+ */
+string ASBeautifier::rtrim(const string& str) const
+{
+ size_t len = str.length();
+ size_t end = str.find_last_not_of(" \t");
+ if (end == string::npos
+ || end == len - 1)
+ return str;
+ string returnStr(str, 0, end + 1);
+ return returnStr;
+}
+
+/**
+ * Copy tempStacks for the copy constructor.
+ * The value of the vectors must also be copied.
+ */
+vector<vector<const string*>*>* ASBeautifier::copyTempStacks(const ASBeautifier& other) const
+{
+ vector<vector<const string*>*>* tempStacksNew = new vector<vector<const string*>*>;
+ vector<vector<const string*>*>::iterator iter;
+ for (iter = other.tempStacks->begin();
+ iter != other.tempStacks->end();
+ ++iter)
+ {
+ vector<const string*>* newVec = new vector<const string*>;
+ *newVec = **iter;
+ tempStacksNew->emplace_back(newVec);
+ }
+ return tempStacksNew;
+}
+
+/**
+ * delete a member vectors to eliminate memory leak reporting
+ */
+void ASBeautifier::deleteBeautifierVectors()
+{
+ beautifierFileType = 9; // reset to an invalid type
+ delete headers;
+ delete nonParenHeaders;
+ delete preBlockStatements;
+ delete preCommandHeaders;
+ delete assignmentOperators;
+ delete nonAssignmentOperators;
+ delete indentableHeaders;
+}
+
+/**
+ * delete a vector object
+ * T is the type of vector
+ * used for all vectors except tempStacks
+ */
+template<typename T>
+void ASBeautifier::deleteContainer(T& container)
+{
+ if (container != nullptr)
+ {
+ container->clear();
+ delete (container);
+ container = nullptr;
+ }
+}
+
+/**
+ * Delete the ASBeautifier vector object.
+ * This is a vector of pointers to ASBeautifier objects allocated with the 'new' operator.
+ * Therefore the ASBeautifier objects have to be deleted in addition to the
+ * ASBeautifier pointer entries.
+ */
+void ASBeautifier::deleteBeautifierContainer(vector<ASBeautifier*>*& container)
+{
+ if (container != nullptr)
+ {
+ vector<ASBeautifier*>::iterator iter = container->begin();
+ while (iter < container->end())
+ {
+ delete *iter;
+ ++iter;
+ }
+ container->clear();
+ delete (container);
+ container = nullptr;
+ }
+}
+
+/**
+ * Delete the tempStacks vector object.
+ * The tempStacks is a vector of pointers to strings allocated with the 'new' operator.
+ * Therefore the strings have to be deleted in addition to the tempStacks entries.
+ */
+void ASBeautifier::deleteTempStacksContainer(vector<vector<const string*>*>*& container)
+{
+ if (container != nullptr)
+ {
+ vector<vector<const string*>*>::iterator iter = container->begin();
+ while (iter < container->end())
+ {
+ delete *iter;
+ ++iter;
+ }
+ container->clear();
+ delete (container);
+ container = nullptr;
+ }
+}
+
+/**
+ * initialize a vector object
+ * T is the type of vector used for all vectors
+ */
+template<typename T>
+void ASBeautifier::initContainer(T& container, T value)
+{
+ // since the ASFormatter object is never deleted,
+ // the existing vectors must be deleted before creating new ones
+ if (container != nullptr)
+ deleteContainer(container);
+ container = value;
+}
+
+/**
+ * Initialize the tempStacks vector object.
+ * The tempStacks is a vector of pointers to strings allocated with the 'new' operator.
+ * Any residual entries are deleted before the vector is initialized.
+ */
+void ASBeautifier::initTempStacksContainer(vector<vector<const string*>*>*& container,
+ vector<vector<const string*>*>* value)
+{
+ if (container != nullptr)
+ deleteTempStacksContainer(container);
+ container = value;
+}
+
+/**
+ * Determine if an assignment statement ends with a comma
+ * that is not in a function argument. It ends with a
+ * comma if a comma is the last char on the line.
+ *
+ * @return true if line ends with a comma, otherwise false.
+ */
+bool ASBeautifier::statementEndsWithComma(const string& line, int index) const
+{
+ assert(line[index] == '=');
+
+ bool isInComment_ = false;
+ bool isInQuote_ = false;
+ int parenCount = 0;
+ size_t lineLength = line.length();
+ size_t i = 0;
+ char quoteChar_ = ' ';
+
+ for (i = index + 1; i < lineLength; ++i)
+ {
+ char ch = line[i];
+
+ if (isInComment_)
+ {
+ if (line.compare(i, 2, "*/") == 0)
+ {
+ isInComment_ = false;
+ ++i;
+ }
+ continue;
+ }
+
+ if (ch == '\\')
+ {
+ ++i;
+ continue;
+ }
+
+ if (isInQuote_)
+ {
+ if (ch == quoteChar_)
+ isInQuote_ = false;
+ continue;
+ }
+
+ if (ch == '"'
+ || (ch == '\'' && !isDigitSeparator(line, i)))
+ {
+ isInQuote_ = true;
+ quoteChar_ = ch;
+ continue;
+ }
+
+ if (line.compare(i, 2, "//") == 0)
+ break;
+
+ if (line.compare(i, 2, "/*") == 0)
+ {
+ if (isLineEndComment(line, i))
+ break;
+ else
+ {
+ isInComment_ = true;
+ ++i;
+ continue;
+ }
+ }
+
+ if (ch == '(')
+ parenCount++;
+ if (ch == ')')
+ parenCount--;
+ }
+ if (isInComment_
+ || isInQuote_
+ || parenCount > 0)
+ return false;
+
+ size_t lastChar = line.find_last_not_of(" \t", i - 1);
+
+ if (lastChar == string::npos || line[lastChar] != ',')
+ return false;
+
+ return true;
+}
+
+/**
+ * check if current comment is a line-end comment
+ *
+ * @return is before a line-end comment.
+ */
+bool ASBeautifier::isLineEndComment(const string& line, int startPos) const
+{
+ assert(line.compare(startPos, 2, "/*") == 0);
+
+ // comment must be closed on this line with nothing after it
+ size_t endNum = line.find("*/", startPos + 2);
+ if (endNum != string::npos)
+ {
+ size_t nextChar = line.find_first_not_of(" \t", endNum + 2);
+ if (nextChar == string::npos)
+ return true;
+ }
+ return false;
+}
+
+/**
+ * get the previous word index for an assignment operator
+ *
+ * @return is the index to the previous word (the in statement indent).
+ */
+int ASBeautifier::getContinuationIndentAssign(const string& line, size_t currPos) const
+{
+ assert(line[currPos] == '=');
+
+ if (currPos == 0)
+ return 0;
+
+ // get the last legal word (may be a number)
+ size_t end = line.find_last_not_of(" \t", currPos - 1);
+ if (end == string::npos || !isLegalNameChar(line[end]))
+ return 0;
+
+ int start; // start of the previous word
+ for (start = end; start > -1; start--)
+ {
+ if (!isLegalNameChar(line[start]) || line[start] == '.')
+ break;
+ }
+ start++;
+
+ return start;
+}
+
+/**
+ * get the instatement indent for a comma
+ *
+ * @return is the indent to the second word on the line (the in statement indent).
+ */
+int ASBeautifier::getContinuationIndentComma(const string& line, size_t currPos) const
+{
+ assert(line[currPos] == ',');
+
+ // get first word on a line
+ size_t indent = line.find_first_not_of(" \t");
+ if (indent == string::npos || !isLegalNameChar(line[indent]))
+ return 0;
+
+ // bypass first word
+ for (; indent < currPos; indent++)
+ {
+ if (!isLegalNameChar(line[indent]))
+ break;
+ }
+ indent++;
+ if (indent >= currPos || indent < 4)
+ return 0;
+
+ // point to second word or assignment operator
+ indent = line.find_first_not_of(" \t", indent);
+ if (indent == string::npos || indent >= currPos)
+ return 0;
+
+ return indent;
+}
+
+/**
+ * get the next word on a line
+ * the argument 'currPos' must point to the current position.
+ *
+ * @return is the next word or an empty string if none found.
+ */
+string ASBeautifier::getNextWord(const string& line, size_t currPos) const
+{
+ size_t lineLength = line.length();
+ // get the last legal word (may be a number)
+ if (currPos == lineLength - 1)
+ return string();
+
+ size_t start = line.find_first_not_of(" \t", currPos + 1);
+ if (start == string::npos || !isLegalNameChar(line[start]))
+ return string();
+
+ size_t end; // end of the current word
+ for (end = start + 1; end <= lineLength; end++)
+ {
+ if (!isLegalNameChar(line[end]) || line[end] == '.')
+ break;
+ }
+
+ return line.substr(start, end - start);
+}
+
+/**
+ * Check if a preprocessor directive is always indented.
+ * C# "region" and "endregion" are always indented.
+ * C/C++ "pragma omp" is always indented.
+ *
+ * @return is true or false.
+ */
+bool ASBeautifier::isIndentedPreprocessor(const string& line, size_t currPos) const
+{
+ assert(line[0] == '#');
+ string nextWord = getNextWord(line, currPos);
+ if (nextWord == "region" || nextWord == "endregion")
+ return true;
+ // is it #pragma omp
+ if (nextWord == "pragma")
+ {
+ // find pragma
+ size_t start = line.find("pragma");
+ if (start == string::npos || !isLegalNameChar(line[start]))
+ return false;
+ // bypass pragma
+ for (; start < line.length(); start++)
+ {
+ if (!isLegalNameChar(line[start]))
+ break;
+ }
+ start++;
+ if (start >= line.length())
+ return false;
+ // point to start of second word
+ start = line.find_first_not_of(" \t", start);
+ if (start == string::npos)
+ return false;
+ // point to end of second word
+ size_t end;
+ for (end = start; end < line.length(); end++)
+ {
+ if (!isLegalNameChar(line[end]))
+ break;
+ }
+ // check for "pragma omp"
+ string word = line.substr(start, end - start);
+ if (word == "omp" || word == "region" || word == "endregion")
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Check if a preprocessor directive is checking for __cplusplus defined.
+ *
+ * @return is true or false.
+ */
+bool ASBeautifier::isPreprocessorConditionalCplusplus(const string& line) const
+{
+ string preproc = trim(line.substr(1));
+ if (preproc.compare(0, 5, "ifdef") == 0 && getNextWord(preproc, 4) == "__cplusplus")
+ return true;
+ if (preproc.compare(0, 2, "if") == 0)
+ {
+ // check for " #if defined(__cplusplus)"
+ size_t charNum = 2;
+ charNum = preproc.find_first_not_of(" \t", charNum);
+ if (charNum != string::npos && preproc.compare(charNum, 7, "defined") == 0)
+ {
+ charNum += 7;
+ charNum = preproc.find_first_not_of(" \t", charNum);
+ if (preproc.compare(charNum, 1, "(") == 0)
+ {
+ ++charNum;
+ charNum = preproc.find_first_not_of(" \t", charNum);
+ if (preproc.compare(charNum, 11, "__cplusplus") == 0)
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/**
+ * Check if a preprocessor definition contains an unterminated comment.
+ * Comments within a preprocessor definition can be continued without the backslash.
+ *
+ * @return is true or false.
+ */
+bool ASBeautifier::isInPreprocessorUnterminatedComment(const string& line)
+{
+ if (!isInPreprocessorComment)
+ {
+ size_t startPos = line.find("/*");
+ if (startPos == string::npos)
+ return false;
+ }
+ size_t endNum = line.find("*/");
+ if (endNum != string::npos)
+ {
+ isInPreprocessorComment = false;
+ return false;
+ }
+ isInPreprocessorComment = true;
+ return true;
+}
+
+void ASBeautifier::popLastContinuationIndent()
+{
+ assert(!continuationIndentStackSizeStack->empty());
+ int previousIndentStackSize = continuationIndentStackSizeStack->back();
+ if (continuationIndentStackSizeStack->size() > 1)
+ continuationIndentStackSizeStack->pop_back();
+ while (previousIndentStackSize < (int) continuationIndentStack->size())
+ continuationIndentStack->pop_back();
+}
+
+// for unit testing
+int ASBeautifier::getBeautifierFileType() const
+{ return beautifierFileType; }
+
+/**
+ * Process preprocessor statements and update the beautifier stacks.
+ */
+void ASBeautifier::processPreprocessor(const string& preproc, const string& line)
+{
+ // When finding a multi-lined #define statement, the original beautifier
+ // 1. sets its isInDefineDefinition flag
+ // 2. clones a new beautifier that will be used for the actual indentation
+ // of the #define. This clone is put into the activeBeautifierStack in order
+ // to be called for the actual indentation.
+ // The original beautifier will have isInDefineDefinition = true, isInDefine = false
+ // The cloned beautifier will have isInDefineDefinition = true, isInDefine = true
+ if (shouldIndentPreprocDefine && preproc == "define" && line[line.length() - 1] == '\\')
+ {
+ if (!isInDefineDefinition)
+ {
+ // this is the original beautifier
+ isInDefineDefinition = true;
+
+ // push a new beautifier into the active stack
+ // this beautifier will be used for the indentation of this define
+ ASBeautifier* defineBeautifier = new ASBeautifier(*this);
+ activeBeautifierStack->emplace_back(defineBeautifier);
+ }
+ else
+ {
+ // the is the cloned beautifier that is in charge of indenting the #define.
+ isInDefine = true;
+ }
+ }
+ else if (preproc.length() >= 2 && preproc.substr(0, 2) == "if")
+ {
+ if (isPreprocessorConditionalCplusplus(line) && !g_preprocessorCppExternCBrace)
+ g_preprocessorCppExternCBrace = 1;
+ // push a new beautifier into the stack
+ waitingBeautifierStackLengthStack->push_back(waitingBeautifierStack->size());
+ activeBeautifierStackLengthStack->push_back(activeBeautifierStack->size());
+ if (activeBeautifierStackLengthStack->back() == 0)
+ waitingBeautifierStack->emplace_back(new ASBeautifier(*this));
+ else
+ waitingBeautifierStack->emplace_back(new ASBeautifier(*activeBeautifierStack->back()));
+ }
+ else if (preproc == "else")
+ {
+ if ((waitingBeautifierStack != nullptr) && !waitingBeautifierStack->empty())
+ {
+ // MOVE current waiting beautifier to active stack.
+ activeBeautifierStack->emplace_back(waitingBeautifierStack->back());
+ waitingBeautifierStack->pop_back();
+ }
+ }
+ else if (preproc == "elif")
+ {
+ if ((waitingBeautifierStack != nullptr) && !waitingBeautifierStack->empty())
+ {
+ // append a COPY current waiting beautifier to active stack, WITHOUT deleting the original.
+ activeBeautifierStack->emplace_back(new ASBeautifier(*(waitingBeautifierStack->back())));
+ }
+ }
+ else if (preproc == "endif")
+ {
+ int stackLength = 0;
+ ASBeautifier* beautifier = nullptr;
+
+ if (waitingBeautifierStackLengthStack != nullptr && !waitingBeautifierStackLengthStack->empty())
+ {
+ stackLength = waitingBeautifierStackLengthStack->back();
+ waitingBeautifierStackLengthStack->pop_back();
+ while ((int) waitingBeautifierStack->size() > stackLength)
+ {
+ beautifier = waitingBeautifierStack->back();
+ waitingBeautifierStack->pop_back();
+ delete beautifier;
+ }
+ }
+
+ if (!activeBeautifierStackLengthStack->empty())
+ {
+ stackLength = activeBeautifierStackLengthStack->back();
+ activeBeautifierStackLengthStack->pop_back();
+ while ((int) activeBeautifierStack->size() > stackLength)
+ {
+ beautifier = activeBeautifierStack->back();
+ activeBeautifierStack->pop_back();
+ delete beautifier;
+ }
+ }
+ }
+}
+
+// Compute the preliminary indentation based on data in the headerStack
+// and data from previous lines.
+// Update the class variable indentCount.
+void ASBeautifier::computePreliminaryIndentation()
+{
+ indentCount = 0;
+ spaceIndentCount = 0;
+ isInClassHeaderTab = false;
+
+ if (isInObjCMethodDefinition && !continuationIndentStack->empty())
+ spaceIndentObjCMethodAlignment = continuationIndentStack->back();
+
+ if (!continuationIndentStack->empty())
+ spaceIndentCount = continuationIndentStack->back();
+
+ for (size_t i = 0; i < headerStack->size(); i++)
+ {
+ isInClass = false;
+
+ if (blockIndent)
+ {
+ // do NOT indent opening block for these headers
+ if (!((*headerStack)[i] == &AS_NAMESPACE
+ || (*headerStack)[i] == &AS_MODULE
+ || (*headerStack)[i] == &AS_CLASS
+ || (*headerStack)[i] == &AS_STRUCT
+ || (*headerStack)[i] == &AS_UNION
+ || (*headerStack)[i] == &AS_INTERFACE
+ || (*headerStack)[i] == &AS_THROWS
+ || (*headerStack)[i] == &AS_STATIC))
+ ++indentCount;
+ }
+ else if (!(i > 0 && (*headerStack)[i - 1] != &AS_OPEN_BRACE
+ && (*headerStack)[i] == &AS_OPEN_BRACE))
+ ++indentCount;
+
+ if (!isJavaStyle() && !namespaceIndent && i > 0
+ && ((*headerStack)[i - 1] == &AS_NAMESPACE
+ || (*headerStack)[i - 1] == &AS_MODULE)
+ && (*headerStack)[i] == &AS_OPEN_BRACE)
+ --indentCount;
+
+ if (isCStyle() && i >= 1
+ && (*headerStack)[i - 1] == &AS_CLASS
+ && (*headerStack)[i] == &AS_OPEN_BRACE)
+ {
+ if (classIndent)
+ ++indentCount;
+ isInClass = true;
+ }
+
+ // is the switchIndent option is on, indent switch statements an additional indent.
+ else if (switchIndent && i > 1
+ && (*headerStack)[i - 1] == &AS_SWITCH
+ && (*headerStack)[i] == &AS_OPEN_BRACE)
+ {
+ ++indentCount;
+ isInSwitch = true;
+ }
+
+ } // end of for loop
+
+ if (isInClassHeader)
+ {
+ if (!isJavaStyle())
+ isInClassHeaderTab = true;
+ if (lineOpensWithLineComment || lineStartsInComment || lineOpensWithComment)
+ {
+ if (!lineBeginsWithOpenBrace)
+ --indentCount;
+ if (!continuationIndentStack->empty())
+ spaceIndentCount -= continuationIndentStack->back();
+ }
+ else if (blockIndent)
+ {
+ if (!lineBeginsWithOpenBrace)
+ ++indentCount;
+ }
+ }
+
+ if (isInClassInitializer || isInEnumTypeID)
+ {
+ indentCount += classInitializerIndents;
+ }
+
+ if (isInEnum && lineBeginsWithComma && !continuationIndentStack->empty())
+ {
+ // unregister '=' indent from the previous line
+ continuationIndentStack->pop_back();
+ isContinuation = false;
+ spaceIndentCount = 0;
+ }
+
+ // Objective-C interface continuation line
+ if (isInObjCInterface)
+ ++indentCount;
+
+ // unindent a class closing brace...
+ if (!lineStartsInComment
+ && isCStyle()
+ && isInClass
+ && classIndent
+ && headerStack->size() >= 2
+ && (*headerStack)[headerStack->size() - 2] == &AS_CLASS
+ && (*headerStack)[headerStack->size() - 1] == &AS_OPEN_BRACE
+ && lineBeginsWithCloseBrace
+ && braceBlockStateStack->back())
+ --indentCount;
+
+ // unindent an indented switch closing brace...
+ else if (!lineStartsInComment
+ && isInSwitch
+ && switchIndent
+ && headerStack->size() >= 2
+ && (*headerStack)[headerStack->size() - 2] == &AS_SWITCH
+ && (*headerStack)[headerStack->size() - 1] == &AS_OPEN_BRACE
+ && lineBeginsWithCloseBrace)
+ --indentCount;
+
+ // handle special case of run-in comment in an indented class statement
+ if (isInClass
+ && classIndent
+ && isInRunInComment
+ && !lineOpensWithComment
+ && headerStack->size() > 1
+ && (*headerStack)[headerStack->size() - 2] == &AS_CLASS)
+ --indentCount;
+
+ if (isInConditional)
+ --indentCount;
+ if (g_preprocessorCppExternCBrace >= 4)
+ --indentCount;
+}
+
+void ASBeautifier::adjustParsedLineIndentation(size_t iPrelim, bool isInExtraHeaderIndent)
+{
+ if (lineStartsInComment)
+ return;
+
+ // unindent a one-line statement in a header indent
+ if (!blockIndent
+ && lineBeginsWithOpenBrace
+ && headerStack->size() < iPrelim
+ && isInExtraHeaderIndent
+ && (lineOpeningBlocksNum > 0 && lineOpeningBlocksNum <= lineClosingBlocksNum)
+ && shouldIndentBracedLine)
+ --indentCount;
+
+ /*
+ * if '{' doesn't follow an immediately previous '{' in the headerStack
+ * (but rather another header such as "for" or "if", then unindent it
+ * by one indentation relative to its block.
+ */
+ else if (!blockIndent
+ && lineBeginsWithOpenBrace
+ && !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum <= lineClosingBlocksNum)
+ && (headerStack->size() > 1 && (*headerStack)[headerStack->size() - 2] != &AS_OPEN_BRACE)
+ && shouldIndentBracedLine)
+ --indentCount;
+
+ // must check one less in headerStack if more than one header on a line (allow-addins)...
+ else if (headerStack->size() > iPrelim + 1
+ && !blockIndent
+ && lineBeginsWithOpenBrace
+ && !(lineOpeningBlocksNum > 0 && lineOpeningBlocksNum <= lineClosingBlocksNum)
+ && (headerStack->size() > 2 && (*headerStack)[headerStack->size() - 3] != &AS_OPEN_BRACE)
+ && shouldIndentBracedLine)
+ --indentCount;
+
+ // unindent a closing brace...
+ else if (lineBeginsWithCloseBrace
+ && shouldIndentBracedLine)
+ --indentCount;
+
+ // correctly indent one-line-blocks...
+ else if (lineOpeningBlocksNum > 0
+ && lineOpeningBlocksNum == lineClosingBlocksNum
+ && previousLineProbationTab)
+ --indentCount;
+
+ if (indentCount < 0)
+ indentCount = 0;
+
+ // take care of extra brace indentation option...
+ if (!lineStartsInComment
+ && braceIndent
+ && shouldIndentBracedLine
+ && (lineBeginsWithOpenBrace || lineBeginsWithCloseBrace))
+ {
+ if (!braceIndentVtk)
+ ++indentCount;
+ else
+ {
+ // determine if a style VTK brace is indented
+ bool haveUnindentedBrace = false;
+ for (size_t i = 0; i < headerStack->size(); i++)
+ {
+ if (((*headerStack)[i] == &AS_NAMESPACE
+ || (*headerStack)[i] == &AS_MODULE
+ || (*headerStack)[i] == &AS_CLASS
+ || (*headerStack)[i] == &AS_STRUCT)
+ && i + 1 < headerStack->size()
+ && (*headerStack)[i + 1] == &AS_OPEN_BRACE)
+ i++;
+ else if (lineBeginsWithOpenBrace)
+ {
+ // don't double count the current brace
+ if (i + 1 < headerStack->size()
+ && (*headerStack)[i] == &AS_OPEN_BRACE)
+ haveUnindentedBrace = true;
+ }
+ else if ((*headerStack)[i] == &AS_OPEN_BRACE)
+ haveUnindentedBrace = true;
+ } // end of for loop
+ if (haveUnindentedBrace)
+ ++indentCount;
+ }
+ }
+}
+
+/**
+ * Compute indentCount adjustment when in a series of else-if statements
+ * and shouldBreakElseIfs is requested.
+ * It increments by one for each 'else' in the tempStack.
+ */
+int ASBeautifier::adjustIndentCountForBreakElseIfComments() const
+{
+ assert(isElseHeaderIndent && !tempStacks->empty());
+ int indentCountIncrement = 0;
+ vector<const string*>* lastTempStack = tempStacks->back();
+ if (lastTempStack != nullptr)
+ {
+ for (size_t i = 0; i < lastTempStack->size(); i++)
+ {
+ if (*lastTempStack->at(i) == AS_ELSE)
+ indentCountIncrement++;
+ }
+ }
+ return indentCountIncrement;
+}
+
+/**
+ * Extract a preprocessor statement without the #.
+ * If a error occurs an empty string is returned.
+ */
+string ASBeautifier::extractPreprocessorStatement(const string& line) const
+{
+ string preproc;
+ size_t start = line.find_first_not_of("#/ \t");
+ if (start == string::npos)
+ return preproc;
+ size_t end = line.find_first_of("/ \t", start);
+ if (end == string::npos)
+ end = line.length();
+ preproc = line.substr(start, end - start);
+ return preproc;
+}
+
+void ASBeautifier::adjustObjCMethodDefinitionIndentation(const string& line_)
+{
+ // register indent for Objective-C continuation line
+ if (line_.length() > 0
+ && (line_[0] == '-' || line_[0] == '+'))
+ {
+ if (shouldAlignMethodColon && objCColonAlignSubsequent != -1)
+ {
+ string convertedLine = getIndentedSpaceEquivalent(line_);
+ colonIndentObjCMethodAlignment = convertedLine.find(':');
+ int objCColonAlignSubsequentIndent = objCColonAlignSubsequent + indentLength;
+ if (objCColonAlignSubsequentIndent > colonIndentObjCMethodAlignment)
+ colonIndentObjCMethodAlignment = objCColonAlignSubsequentIndent;
+ }
+ else if (continuationIndentStack->empty()
+ || continuationIndentStack->back() == 0)
+ {
+ continuationIndentStack->emplace_back(indentLength);
+ isContinuation = true;
+ }
+ }
+ // set indent for last definition line
+ else if (!lineBeginsWithOpenBrace)
+ {
+ if (shouldAlignMethodColon)
+ spaceIndentCount = computeObjCColonAlignment(line_, colonIndentObjCMethodAlignment);
+ else if (continuationIndentStack->empty())
+ spaceIndentCount = spaceIndentObjCMethodAlignment;
+ }
+}
+
+void ASBeautifier::adjustObjCMethodCallIndentation(const string& line_)
+{
+ static int keywordIndentObjCMethodAlignment = 0;
+ if (shouldAlignMethodColon && objCColonAlignSubsequent != -1)
+ {
+ if (isInObjCMethodCallFirst)
+ {
+ isInObjCMethodCallFirst = false;
+ string convertedLine = getIndentedSpaceEquivalent(line_);
+ bracePosObjCMethodAlignment = convertedLine.find('[');
+ keywordIndentObjCMethodAlignment =
+ getObjCFollowingKeyword(convertedLine, bracePosObjCMethodAlignment);
+ colonIndentObjCMethodAlignment = convertedLine.find(':');
+ if (colonIndentObjCMethodAlignment >= 0)
+ {
+ int objCColonAlignSubsequentIndent = objCColonAlignSubsequent + indentLength;
+ if (objCColonAlignSubsequentIndent > colonIndentObjCMethodAlignment)
+ colonIndentObjCMethodAlignment = objCColonAlignSubsequentIndent;
+ if (lineBeginsWithOpenBrace)
+ colonIndentObjCMethodAlignment -= indentLength;
+ }
+ }
+ else
+ {
+ if (line_.find(':') != string::npos)
+ {
+ if (colonIndentObjCMethodAlignment < 0)
+ spaceIndentCount += computeObjCColonAlignment(line_, objCColonAlignSubsequent);
+ else if (objCColonAlignSubsequent > colonIndentObjCMethodAlignment)
+ spaceIndentCount = computeObjCColonAlignment(line_, objCColonAlignSubsequent);
+ else
+ spaceIndentCount = computeObjCColonAlignment(line_, colonIndentObjCMethodAlignment);
+ }
+ else
+ {
+ if (spaceIndentCount < colonIndentObjCMethodAlignment)
+ spaceIndentCount += keywordIndentObjCMethodAlignment;
+ }
+ }
+ }
+ else // align keywords instead of colons
+ {
+ if (isInObjCMethodCallFirst)
+ {
+ isInObjCMethodCallFirst = false;
+ string convertedLine = getIndentedSpaceEquivalent(line_);
+ bracePosObjCMethodAlignment = convertedLine.find('[');
+ keywordIndentObjCMethodAlignment =
+ getObjCFollowingKeyword(convertedLine, bracePosObjCMethodAlignment);
+ }
+ else
+ {
+ if (spaceIndentCount < keywordIndentObjCMethodAlignment + bracePosObjCMethodAlignment)
+ spaceIndentCount += keywordIndentObjCMethodAlignment;
+ }
+ }
+}
+
+/**
+ * Clear the variables used to align the Objective-C method definitions.
+ */
+void ASBeautifier::clearObjCMethodDefinitionAlignment()
+{
+ assert(isImmediatelyPostObjCMethodDefinition);
+ spaceIndentCount = 0;
+ spaceIndentObjCMethodAlignment = 0;
+ colonIndentObjCMethodAlignment = 0;
+ isInObjCMethodDefinition = false;
+ isImmediatelyPostObjCMethodDefinition = false;
+ if (!continuationIndentStack->empty())
+ continuationIndentStack->pop_back();
+}
+
+/**
+ * Compute the spaceIndentCount necessary to align the current line colon
+ * with the colon position in the argument.
+ * If it cannot be aligned indentLength is returned and a new colon
+ * position is calculated.
+ */
+int ASBeautifier::computeObjCColonAlignment(const string& line, int colonAlignPosition) const
+{
+ int colonPosition = line.find(':');
+ if (colonPosition < 0 || colonPosition > colonAlignPosition)
+ return indentLength;
+ return (colonAlignPosition - colonPosition);
+}
+
+/*
+ * Compute postition of the keyword following the method call object.
+ */
+int ASBeautifier::getObjCFollowingKeyword(const string& line, int bracePos) const
+{
+ assert(line[bracePos] == '[');
+ size_t firstText = line.find_first_not_of(" \t", bracePos + 1);
+ if (firstText == string::npos)
+ return -(indentCount * indentLength - 1);
+ size_t searchBeg = firstText;
+ size_t objectEnd = 0; // end of object text
+ if (line[searchBeg] == '[')
+ {
+ objectEnd = line.find(']', searchBeg + 1);
+ if (objectEnd == string::npos)
+ return 0;
+ }
+ else
+ {
+ if (line[searchBeg] == '(')
+ {
+ searchBeg = line.find(')', searchBeg + 1);
+ if (searchBeg == string::npos)
+ return 0;
+ }
+ // bypass the object name
+ objectEnd = line.find_first_of(" \t", searchBeg + 1);
+ if (objectEnd == string::npos)
+ return 0;
+ --objectEnd;
+ }
+ size_t keyPos = line.find_first_not_of(" \t", objectEnd + 1);
+ if (keyPos == string::npos)
+ return 0;
+ return keyPos - firstText;
+}
+
+/**
+ * Get a line using the current space indent with all tabs replaced by spaces.
+ * The indentCount is NOT included
+ * Needed to compute an accurate alignment.
+ */
+string ASBeautifier::getIndentedSpaceEquivalent(const string& line_) const
+{
+ string spaceIndent;
+ spaceIndent.append(spaceIndentCount, ' ');
+ string convertedLine = spaceIndent + line_;
+ for (size_t i = spaceIndent.length(); i < convertedLine.length(); i++)
+ {
+ if (convertedLine[i] == '\t')
+ {
+ size_t numSpaces = indentLength - (i % indentLength);
+ convertedLine.replace(i, 1, numSpaces, ' ');
+ i += indentLength - 1;
+ }
+ }
+ return convertedLine;
+}
+
+/**
+ * Parse the current line to update indentCount and spaceIndentCount.
+ */
+void ASBeautifier::parseCurrentLine(const string& line)
+{
+ bool isInLineComment = false;
+ bool isInOperator = false;
+ bool isSpecialChar = false;
+ bool haveCaseIndent = false;
+ bool haveAssignmentThisLine = false;
+ bool closingBraceReached = false;
+ bool previousLineProbation = (probationHeader != nullptr);
+ char ch = ' ';
+ int tabIncrementIn = 0;
+ if (isInQuote
+ && !haveLineContinuationChar
+ && !isInVerbatimQuote
+ && !isInAsm)
+ isInQuote = false; // missing closing quote
+ haveLineContinuationChar = false;
+
+ for (size_t i = 0; i < line.length(); i++)
+ {
+ ch = line[i];
+
+ if (isInBeautifySQL)
+ continue;
+
+ // handle special characters (i.e. backslash+character such as \n, \t, ...)
+ if (isInQuote && !isInVerbatimQuote)
+ {
+ if (isSpecialChar)
+ {
+ isSpecialChar = false;
+ continue;
+ }
+ if (line.compare(i, 2, "\\\\") == 0)
+ {
+ i++;
+ continue;
+ }
+ if (ch == '\\')
+ {
+ if (peekNextChar(line, i) == ' ') // is this '\' at end of line
+ haveLineContinuationChar = true;
+ else
+ isSpecialChar = true;
+ continue;
+ }
+ }
+ else if (isInDefine && ch == '\\')
+ continue;
+
+ // bypass whitespace here
+ if (isWhiteSpace(ch))
+ {
+ if (ch == '\t')
+ tabIncrementIn += convertTabToSpaces(i, tabIncrementIn);
+ continue;
+ }
+
+ // handle quotes (such as 'x' and "Hello Dolly")
+ if (!(isInComment || isInLineComment)
+ && (ch == '"'
+ || (ch == '\'' && !isDigitSeparator(line, i))))
+ {
+ if (!isInQuote)
+ {
+ quoteChar = ch;
+ isInQuote = true;
+ char prevCh = i > 0 ? line[i - 1] : ' ';
+ if (isCStyle() && prevCh == 'R')
+ {
+ int parenPos = line.find('(', i);
+ if (parenPos != -1)
+ {
+ isInVerbatimQuote = true;
+ verbatimDelimiter = line.substr(i + 1, parenPos - i - 1);
+ }
+ }
+ else if (isSharpStyle() && prevCh == '@')
+ isInVerbatimQuote = true;
+ // check for "C" following "extern"
+ else if (g_preprocessorCppExternCBrace == 2 && line.compare(i, 3, "\"C\"") == 0)
+ ++g_preprocessorCppExternCBrace;
+ }
+ else if (isInVerbatimQuote && ch == '"')
+ {
+ if (isCStyle())
+ {
+ string delim = ')' + verbatimDelimiter;
+ int delimStart = i - delim.length();
+ if (delimStart > 0 && line.substr(delimStart, delim.length()) == delim)
+ {
+ isInQuote = false;
+ isInVerbatimQuote = false;
+ }
+ }
+ else if (isSharpStyle())
+ {
+ if (line.compare(i, 2, "\"\"") == 0)
+ i++;
+ else
+ {
+ isInQuote = false;
+ isInVerbatimQuote = false;
+ continue;
+ }
+ }
+ }
+ else if (quoteChar == ch)
+ {
+ isInQuote = false;
+ isContinuation = true;
+ continue;
+ }
+ }
+ if (isInQuote)
+ continue;
+
+ // handle comments
+
+ if (!(isInComment || isInLineComment) && line.compare(i, 2, "//") == 0)
+ {
+ // if there is a 'case' statement after these comments unindent by 1
+ if (isCaseHeaderCommentIndent)
+ --indentCount;
+ // isElseHeaderIndent is set by ASFormatter if shouldBreakElseIfs is requested
+ // if there is an 'else' after these comments a tempStacks indent is required
+ if (isElseHeaderIndent && lineOpensWithLineComment && !tempStacks->empty())
+ indentCount += adjustIndentCountForBreakElseIfComments();
+ isInLineComment = true;
+ i++;
+ continue;
+ }
+ else if (!(isInComment || isInLineComment) && line.compare(i, 2, "/*") == 0)
+ {
+ // if there is a 'case' statement after these comments unindent by 1
+ if (isCaseHeaderCommentIndent && lineOpensWithComment)
+ --indentCount;
+ // isElseHeaderIndent is set by ASFormatter if shouldBreakElseIfs is requested
+ // if there is an 'else' after these comments a tempStacks indent is required
+ if (isElseHeaderIndent && lineOpensWithComment && !tempStacks->empty())
+ indentCount += adjustIndentCountForBreakElseIfComments();
+ isInComment = true;
+ i++;
+ if (!lineOpensWithComment) // does line start with comment?
+ blockCommentNoIndent = true; // if no, cannot indent continuation lines
+ continue;
+ }
+ else if ((isInComment || isInLineComment) && line.compare(i, 2, "*/") == 0)
+ {
+ size_t firstText = line.find_first_not_of(" \t");
+ // if there is a 'case' statement after these comments unindent by 1
+ // only if the ending comment is the first entry on the line
+ if (isCaseHeaderCommentIndent && firstText == i)
+ --indentCount;
+ // if this comment close starts the line, must check for else-if indent
+ // isElseHeaderIndent is set by ASFormatter if shouldBreakElseIfs is requested
+ // if there is an 'else' after these comments a tempStacks indent is required
+ if (firstText == i)
+ {
+ if (isElseHeaderIndent && !lineOpensWithComment && !tempStacks->empty())
+ indentCount += adjustIndentCountForBreakElseIfComments();
+ }
+ isInComment = false;
+ i++;
+ blockCommentNoIndent = false; // ok to indent next comment
+ continue;
+ }
+ // treat indented preprocessor lines as a line comment
+ else if (line[0] == '#' && isIndentedPreprocessor(line, i))
+ {
+ isInLineComment = true;
+ }
+
+ if (isInLineComment)
+ {
+ // bypass rest of the comment up to the comment end
+ while (i + 1 < line.length())
+ i++;
+
+ continue;
+ }
+ if (isInComment)
+ {
+ // if there is a 'case' statement after these comments unindent by 1
+ if (!lineOpensWithComment && isCaseHeaderCommentIndent)
+ --indentCount;
+ // isElseHeaderIndent is set by ASFormatter if shouldBreakElseIfs is requested
+ // if there is an 'else' after these comments a tempStacks indent is required
+ if (!lineOpensWithComment && isElseHeaderIndent && !tempStacks->empty())
+ indentCount += adjustIndentCountForBreakElseIfComments();
+ // bypass rest of the comment up to the comment end
+ while (i + 1 < line.length()
+ && line.compare(i + 1, 2, "*/") != 0)
+ i++;
+
+ continue;
+ }
+
+ // if we have reached this far then we are NOT in a comment or string of special character...
+
+ if (probationHeader != nullptr)
+ {
+ if ((probationHeader == &AS_STATIC && ch == '{')
+ || (probationHeader == &AS_SYNCHRONIZED && ch == '('))
+ {
+ // insert the probation header as a new header
+ isInHeader = true;
+ headerStack->emplace_back(probationHeader);
+
+ // handle the specific probation header
+ isInConditional = (probationHeader == &AS_SYNCHRONIZED);
+
+ isContinuation = false;
+ // if the probation comes from the previous line, then indent by 1 tab count.
+ if (previousLineProbation
+ && ch == '{'
+ && !(blockIndent && probationHeader == &AS_STATIC))
+ {
+ ++indentCount;
+ previousLineProbationTab = true;
+ }
+ previousLineProbation = false;
+ }
+
+ // dismiss the probation header
+ probationHeader = nullptr;
+ }
+
+ prevNonSpaceCh = currentNonSpaceCh;
+ currentNonSpaceCh = ch;
+ if (!isLegalNameChar(ch) && ch != ',' && ch != ';')
+ {
+ prevNonLegalCh = currentNonLegalCh;
+ currentNonLegalCh = ch;
+ }
+
+ if (isInHeader)
+ {
+ isInHeader = false;
+ currentHeader = headerStack->back();
+ }
+ else
+ currentHeader = nullptr;
+
+ if (isCStyle() && isInTemplate
+ && (ch == '<' || ch == '>')
+ && !(line.length() > i + 1 && line.compare(i, 2, ">=") == 0))
+ {
+ if (ch == '<')
+ {
+ ++templateDepth;
+ continuationIndentStackSizeStack->push_back(continuationIndentStack->size());
+ registerContinuationIndent(line, i, spaceIndentCount, tabIncrementIn, 0, true);
+ }
+ else if (ch == '>')
+ {
+ popLastContinuationIndent();
+ if (--templateDepth <= 0)
+ {
+ ch = ';';
+ isInTemplate = false;
+ templateDepth = 0;
+ }
+ }
+ }
+
+ // handle parentheses
+ if (ch == '(' || ch == '[' || ch == ')' || ch == ']')
+ {
+ if (ch == '(' || ch == '[')
+ {
+ isInOperator = false;
+ // if have a struct header, this is a declaration not a definition
+ if (ch == '('
+ && !headerStack->empty()
+ && headerStack->back() == &AS_STRUCT)
+ {
+ headerStack->pop_back();
+ isInClassHeader = false;
+ if (line.find(AS_STRUCT, 0) > i) // if not on this line
+ indentCount -= classInitializerIndents;
+ if (indentCount < 0)
+ indentCount = 0;
+ }
+
+ if (parenDepth == 0)
+ {
+ parenStatementStack->push_back(isContinuation);
+ isContinuation = true;
+ }
+ parenDepth++;
+ if (ch == '[')
+ {
+ ++squareBracketCount;
+ if (squareBracketCount == 1 && isCStyle())
+ {
+ isInObjCMethodCall = true;
+ isInObjCMethodCallFirst = true;
+ }
+ }
+
+ continuationIndentStackSizeStack->push_back(continuationIndentStack->size());
+
+ if (currentHeader != nullptr)
+ registerContinuationIndent(line, i, spaceIndentCount, tabIncrementIn, minConditionalIndent, true);
+ else
+ registerContinuationIndent(line, i, spaceIndentCount, tabIncrementIn, 0, true);
+ }
+ else if (ch == ')' || ch == ']')
+ {
+ if (ch == ']')
+ --squareBracketCount;
+ if (squareBracketCount <= 0)
+ {
+ squareBracketCount = 0;
+ if (isInObjCMethodCall)
+ isImmediatelyPostObjCMethodCall = true;
+ }
+ foundPreCommandHeader = false;
+ parenDepth--;
+ if (parenDepth == 0)
+ {
+ if (!parenStatementStack->empty()) // in case of unmatched closing parens
+ {
+ isContinuation = parenStatementStack->back();
+ parenStatementStack->pop_back();
+ }
+ isInAsm = false;
+ isInConditional = false;
+ }
+
+ if (!continuationIndentStackSizeStack->empty())
+ {
+ popLastContinuationIndent();
+
+ if (!parenIndentStack->empty())
+ {
+ int poppedIndent = parenIndentStack->back();
+ parenIndentStack->pop_back();
+
+ if (i == 0)
+ spaceIndentCount = poppedIndent;
+ }
+ }
+ }
+ continue;
+ }
+
+ if (ch == '{')
+ {
+ // first, check if '{' is a block-opener or a static-array opener
+ bool isBlockOpener = ((prevNonSpaceCh == '{' && braceBlockStateStack->back())
+ || prevNonSpaceCh == '}'
+ || prevNonSpaceCh == ')'
+ || prevNonSpaceCh == ';'
+ || peekNextChar(line, i) == '{'
+ || foundPreCommandHeader
+ || foundPreCommandMacro
+ || isInClassHeader
+ || (isInClassInitializer && !isLegalNameChar(prevNonSpaceCh))
+ || isNonInStatementArray
+ || isInObjCMethodDefinition
+ || isInObjCInterface
+ || isSharpAccessor
+ || isSharpDelegate
+ || isInExternC
+ || isInAsmBlock
+ || getNextWord(line, i) == AS_NEW
+ || (isInDefine
+ && (prevNonSpaceCh == '('
+ || isLegalNameChar(prevNonSpaceCh))));
+
+ if (isInObjCMethodDefinition)
+ {
+ objCColonAlignSubsequent = 0;
+ isImmediatelyPostObjCMethodDefinition = true;
+ if (lineBeginsWithOpenBrace) // for run-in braces
+ clearObjCMethodDefinitionAlignment();
+ }
+
+ if (!isBlockOpener && !isContinuation && !isInClassInitializer && !isInEnum)
+ {
+ if (headerStack->empty())
+ isBlockOpener = true;
+ else if (headerStack->back() == &AS_OPEN_BRACE
+ && headerStack->size() >= 2)
+ {
+ if ((*headerStack)[headerStack->size() - 2] == &AS_NAMESPACE
+ || (*headerStack)[headerStack->size() - 2] == &AS_MODULE
+ || (*headerStack)[headerStack->size() - 2] == &AS_CLASS
+ || (*headerStack)[headerStack->size() - 2] == &AS_INTERFACE
+ || (*headerStack)[headerStack->size() - 2] == &AS_STRUCT
+ || (*headerStack)[headerStack->size() - 2] == &AS_UNION)
+ isBlockOpener = true;
+ }
+ else if (headerStack->back() == &AS_NAMESPACE
+ || headerStack->back() == &AS_MODULE
+ || headerStack->back() == &AS_CLASS
+ || headerStack->back() == &AS_INTERFACE
+ || headerStack->back() == &AS_STRUCT
+ || headerStack->back() == &AS_UNION)
+ isBlockOpener = true;
+ }
+
+ if (!isBlockOpener && currentHeader != nullptr)
+ {
+ for (size_t n = 0; n < nonParenHeaders->size(); n++)
+ if (currentHeader == (*nonParenHeaders)[n])
+ {
+ isBlockOpener = true;
+ break;
+ }
+ }
+
+ braceBlockStateStack->push_back(isBlockOpener);
+
+ if (!isBlockOpener)
+ {
+ continuationIndentStackSizeStack->push_back(continuationIndentStack->size());
+ registerContinuationIndent(line, i, spaceIndentCount, tabIncrementIn, 0, true);
+ parenDepth++;
+ if (i == 0)
+ shouldIndentBracedLine = false;
+ isInEnumTypeID = false;
+
+ continue;
+ }
+
+ // this brace is a block opener...
+
+ ++lineOpeningBlocksNum;
+
+ if (isInClassInitializer || isInEnumTypeID)
+ {
+ // decrease tab count if brace is broken
+ if (lineBeginsWithOpenBrace)
+ {
+ indentCount -= classInitializerIndents;
+ // decrease one more if an empty class
+ if (!headerStack->empty()
+ && (*headerStack).back() == &AS_CLASS)
+ {
+ int nextChar = getNextProgramCharDistance(line, i);
+ if ((int) line.length() > nextChar && line[nextChar] == '}')
+ --indentCount;
+ }
+ }
+ }
+
+ if (isInObjCInterface)
+ {
+ isInObjCInterface = false;
+ if (lineBeginsWithOpenBrace)
+ --indentCount;
+ }
+
+ if (braceIndent && !namespaceIndent && !headerStack->empty()
+ && ((*headerStack).back() == &AS_NAMESPACE
+ || (*headerStack).back() == &AS_MODULE))
+ {
+ shouldIndentBracedLine = false;
+ --indentCount;
+ }
+
+ // an indentable struct is treated like a class in the header stack
+ if (!headerStack->empty()
+ && (*headerStack).back() == &AS_STRUCT
+ && isInIndentableStruct)
+ (*headerStack).back() = &AS_CLASS;
+
+ squareBracketDepthStack->emplace_back(parenDepth);
+ blockStatementStack->push_back(isContinuation);
+
+ if (!continuationIndentStack->empty())
+ {
+ // completely purge the inStatementIndentStack
+ while (!continuationIndentStack->empty())
+ popLastContinuationIndent();
+ if (isInClassInitializer || isInClassHeaderTab)
+ {
+ if (lineBeginsWithOpenBrace || lineBeginsWithComma)
+ spaceIndentCount = 0;
+ }
+ else
+ spaceIndentCount = 0;
+ }
+
+ blockTabCount += (isContinuation ? 1 : 0);
+ if (g_preprocessorCppExternCBrace == 3)
+ ++g_preprocessorCppExternCBrace;
+ parenDepth = 0;
+ isInClassHeader = false;
+ isInClassHeaderTab = false;
+ isInClassInitializer = false;
+ isInEnumTypeID = false;
+ isContinuation = false;
+ isInQuestion = false;
+ isInLet = false;
+ foundPreCommandHeader = false;
+ foundPreCommandMacro = false;
+ isInExternC = false;
+
+ tempStacks->emplace_back(new vector<const string*>);
+ headerStack->emplace_back(&AS_OPEN_BRACE);
+ lastLineHeader = &AS_OPEN_BRACE;
+
+ continue;
+ } // end '{'
+
+ //check if a header has been reached
+ bool isPotentialHeader = isCharPotentialHeader(line, i);
+
+ if (isPotentialHeader && squareBracketCount == 0)
+ {
+ const string* newHeader = findHeader(line, i, headers);
+
+ // Qt headers may be variables in C++
+ if (isCStyle()
+ && (newHeader == &AS_FOREVER || newHeader == &AS_FOREACH))
+ {
+ if (line.find_first_of("=;", i) != string::npos)
+ newHeader = nullptr;
+ }
+ else if (newHeader == &AS_USING
+ && ASBeautifier::peekNextChar(line, i + (*newHeader).length() - 1) != '(')
+ newHeader = nullptr;
+
+ if (newHeader != nullptr)
+ {
+ // if we reached here, then this is a header...
+ bool isIndentableHeader = true;
+
+ isInHeader = true;
+
+ vector<const string*>* lastTempStack = nullptr;;
+ if (!tempStacks->empty())
+ lastTempStack = tempStacks->back();
+
+ // if a new block is opened, push a new stack into tempStacks to hold the
+ // future list of headers in the new block.
+
+ // take care of the special case: 'else if (...)'
+ if (newHeader == &AS_IF && lastLineHeader == &AS_ELSE)
+ {
+ headerStack->pop_back();
+ }
+
+ // take care of 'else'
+ else if (newHeader == &AS_ELSE)
+ {
+ if (lastTempStack != nullptr)
+ {
+ int indexOfIf = indexOf(*lastTempStack, &AS_IF);
+ if (indexOfIf != -1)
+ {
+ // recreate the header list in headerStack up to the previous 'if'
+ // from the temporary snapshot stored in lastTempStack.
+ int restackSize = lastTempStack->size() - indexOfIf - 1;
+ for (int r = 0; r < restackSize; r++)
+ {
+ headerStack->emplace_back(lastTempStack->back());
+ lastTempStack->pop_back();
+ }
+ if (!closingBraceReached)
+ indentCount += restackSize;
+ }
+ /*
+ * If the above if is not true, i.e. no 'if' before the 'else',
+ * then nothing beautiful will come out of this...
+ * I should think about inserting an Exception here to notify the caller of this...
+ */
+ }
+ }
+
+ // check if 'while' closes a previous 'do'
+ else if (newHeader == &AS_WHILE)
+ {
+ if (lastTempStack != nullptr)
+ {
+ int indexOfDo = indexOf(*lastTempStack, &AS_DO);
+ if (indexOfDo != -1)
+ {
+ // recreate the header list in headerStack up to the previous 'do'
+ // from the temporary snapshot stored in lastTempStack.
+ int restackSize = lastTempStack->size() - indexOfDo - 1;
+ for (int r = 0; r < restackSize; r++)
+ {
+ headerStack->emplace_back(lastTempStack->back());
+ lastTempStack->pop_back();
+ }
+ if (!closingBraceReached)
+ indentCount += restackSize;
+ }
+ }
+ }
+ // check if 'catch' closes a previous 'try' or 'catch'
+ else if (newHeader == &AS_CATCH || newHeader == &AS_FINALLY)
+ {
+ if (lastTempStack != nullptr)
+ {
+ int indexOfTry = indexOf(*lastTempStack, &AS_TRY);
+ if (indexOfTry == -1)
+ indexOfTry = indexOf(*lastTempStack, &AS_CATCH);
+ if (indexOfTry != -1)
+ {
+ // recreate the header list in headerStack up to the previous 'try'
+ // from the temporary snapshot stored in lastTempStack.
+ int restackSize = lastTempStack->size() - indexOfTry - 1;
+ for (int r = 0; r < restackSize; r++)
+ {
+ headerStack->emplace_back(lastTempStack->back());
+ lastTempStack->pop_back();
+ }
+
+ if (!closingBraceReached)
+ indentCount += restackSize;
+ }
+ }
+ }
+ else if (newHeader == &AS_CASE)
+ {
+ isInCase = true;
+ if (!haveCaseIndent)
+ {
+ haveCaseIndent = true;
+ if (!lineBeginsWithOpenBrace)
+ --indentCount;
+ }
+ }
+ else if (newHeader == &AS_DEFAULT)
+ {
+ isInCase = true;
+ --indentCount;
+ }
+ else if (newHeader == &AS_STATIC
+ || newHeader == &AS_SYNCHRONIZED)
+ {
+ if (!headerStack->empty()
+ && (headerStack->back() == &AS_STATIC
+ || headerStack->back() == &AS_SYNCHRONIZED))
+ {
+ isIndentableHeader = false;
+ }
+ else
+ {
+ isIndentableHeader = false;
+ probationHeader = newHeader;
+ }
+ }
+ else if (newHeader == &AS_TEMPLATE)
+ {
+ isInTemplate = true;
+ isIndentableHeader = false;
+ }
+
+ if (isIndentableHeader)
+ {
+ headerStack->emplace_back(newHeader);
+ isContinuation = false;
+ if (indexOf(*nonParenHeaders, newHeader) == -1)
+ {
+ isInConditional = true;
+ }
+ lastLineHeader = newHeader;
+ }
+ else
+ isInHeader = false;
+
+ i += newHeader->length() - 1;
+
+ continue;
+ } // newHeader != nullptr
+
+ if (findHeader(line, i, preCommandHeaders) != nullptr)
+ foundPreCommandHeader = true;
+
+ // Objective-C NSException macros are preCommandHeaders
+ if (isCStyle() && findKeyword(line, i, AS_NS_DURING))
+ foundPreCommandMacro = true;
+ if (isCStyle() && findKeyword(line, i, AS_NS_HANDLER))
+ foundPreCommandMacro = true;
+
+ if (parenDepth == 0 && findKeyword(line, i, AS_ENUM))
+ isInEnum = true;
+
+ if (isSharpStyle() && findKeyword(line, i, AS_LET))
+ isInLet = true;
+
+ } // isPotentialHeader
+
+ if (ch == '?')
+ isInQuestion = true;
+
+ // special handling of colons
+ if (ch == ':')
+ {
+ if (line.length() > i + 1 && line[i + 1] == ':') // look for ::
+ {
+ ++i;
+ continue;
+ }
+ else if (isInQuestion)
+ {
+ // do nothing special
+ }
+ else if (parenDepth > 0)
+ {
+ // found a 'for' loop or an objective-C statement
+ // so do nothing special
+ }
+ else if (isInEnum)
+ {
+ // found an enum with a base-type
+ isInEnumTypeID = true;
+ if (i == 0)
+ indentCount += classInitializerIndents;
+ }
+ else if (isCStyle()
+ && !isInCase
+ && (prevNonSpaceCh == ')' || foundPreCommandHeader))
+ {
+ // found a 'class' c'tor initializer
+ isInClassInitializer = true;
+ registerContinuationIndentColon(line, i, tabIncrementIn);
+ if (i == 0)
+ indentCount += classInitializerIndents;
+ }
+ else if (isInClassHeader || isInObjCInterface)
+ {
+ // is in a 'class A : public B' definition
+ isInClassHeaderTab = true;
+ registerContinuationIndentColon(line, i, tabIncrementIn);
+ }
+ else if (isInAsm || isInAsmOneLine || isInAsmBlock)
+ {
+ // do nothing special
+ }
+ else if (isDigit(peekNextChar(line, i)))
+ {
+ // found a bit field - do nothing special
+ }
+ else if (isCStyle() && isInClass && prevNonSpaceCh != ')')
+ {
+ // found a 'private:' or 'public:' inside a class definition
+ --indentCount;
+ if (modifierIndent)
+ spaceIndentCount += (indentLength / 2);
+ }
+ else if (isCStyle() && !isInClass
+ && headerStack->size() >= 2
+ && (*headerStack)[headerStack->size() - 2] == &AS_CLASS
+ && (*headerStack)[headerStack->size() - 1] == &AS_OPEN_BRACE)
+ {
+ // found a 'private:' or 'public:' inside a class definition
+ // and on the same line as the class opening brace
+ // do nothing
+ }
+ else if (isJavaStyle() && lastLineHeader == &AS_FOR)
+ {
+ // found a java for-each statement
+ // so do nothing special
+ }
+ else
+ {
+ currentNonSpaceCh = ';'; // so that braces after the ':' will appear as block-openers
+ char peekedChar = peekNextChar(line, i);
+ if (isInCase)
+ {
+ isInCase = false;
+ ch = ';'; // from here on, treat char as ';'
+ }
+ else if (isCStyle() || (isSharpStyle() && peekedChar == ';'))
+ {
+ // is in a label (e.g. 'label1:')
+ if (labelIndent)
+ --indentCount; // unindent label by one indent
+ else if (!lineBeginsWithOpenBrace)
+ indentCount = 0; // completely flush indent to left
+ }
+ }
+ }
+
+ if ((ch == ';' || (parenDepth > 0 && ch == ',')) && !continuationIndentStackSizeStack->empty())
+ while ((int) continuationIndentStackSizeStack->back() + (parenDepth > 0 ? 1 : 0)
+ < (int) continuationIndentStack->size())
+ continuationIndentStack->pop_back();
+
+ else if (ch == ',' && isInEnum && isNonInStatementArray && !continuationIndentStack->empty())
+ continuationIndentStack->pop_back();
+
+ // handle commas
+ // previous "isInStatement" will be from an assignment operator or class initializer
+ if (ch == ',' && parenDepth == 0 && !isContinuation && !isNonInStatementArray)
+ {
+ // is comma at end of line
+ size_t nextChar = line.find_first_not_of(" \t", i + 1);
+ if (nextChar != string::npos)
+ {
+ if (line.compare(nextChar, 2, "//") == 0
+ || line.compare(nextChar, 2, "/*") == 0)
+ nextChar = string::npos;
+ }
+ // register indent
+ if (nextChar == string::npos)
+ {
+ // register indent at previous word
+ if (isJavaStyle() && isInClassHeader)
+ {
+ // do nothing for now
+ }
+ // register indent at second word on the line
+ else if (!isInTemplate && !isInClassHeaderTab && !isInClassInitializer)
+ {
+ int prevWord = getContinuationIndentComma(line, i);
+ int continuationIndentCount = prevWord + spaceIndentCount + tabIncrementIn;
+ continuationIndentStack->emplace_back(continuationIndentCount);
+ isContinuation = true;
+ }
+ }
+ }
+ // handle comma first initializers
+ if (ch == ',' && parenDepth == 0 && lineBeginsWithComma
+ && (isInClassInitializer || isInClassHeaderTab))
+ spaceIndentCount = 0;
+
+ // handle ends of statements
+ if ((ch == ';' && parenDepth == 0) || ch == '}')
+ {
+ if (ch == '}')
+ {
+ // first check if this '}' closes a previous block, or a static array...
+ if (braceBlockStateStack->size() > 1)
+ {
+ bool braceBlockState = braceBlockStateStack->back();
+ braceBlockStateStack->pop_back();
+ if (!braceBlockState)
+ {
+ if (!continuationIndentStackSizeStack->empty())
+ {
+ // this brace is a static array
+ popLastContinuationIndent();
+ parenDepth--;
+ if (i == 0)
+ shouldIndentBracedLine = false;
+
+ if (!parenIndentStack->empty())
+ {
+ int poppedIndent = parenIndentStack->back();
+ parenIndentStack->pop_back();
+ if (i == 0)
+ spaceIndentCount = poppedIndent;
+ }
+ }
+ continue;
+ }
+ }
+
+ // this brace is block closer...
+
+ ++lineClosingBlocksNum;
+
+ if (!continuationIndentStackSizeStack->empty())
+ popLastContinuationIndent();
+
+ if (!squareBracketDepthStack->empty())
+ {
+ parenDepth = squareBracketDepthStack->back();
+ squareBracketDepthStack->pop_back();
+ isContinuation = blockStatementStack->back();
+ blockStatementStack->pop_back();
+
+ if (isContinuation)
+ blockTabCount--;
+ }
+
+ closingBraceReached = true;
+ if (i == 0)
+ spaceIndentCount = 0;
+ isInAsmBlock = false;
+ isInAsm = isInAsmOneLine = isInQuote = false; // close these just in case
+
+ int headerPlace = indexOf(*headerStack, &AS_OPEN_BRACE);
+ if (headerPlace != -1)
+ {
+ const string* popped = headerStack->back();
+ while (popped != &AS_OPEN_BRACE)
+ {
+ headerStack->pop_back();
+ popped = headerStack->back();
+ }
+ headerStack->pop_back();
+
+ if (headerStack->empty())
+ g_preprocessorCppExternCBrace = 0;
+
+ // do not indent namespace brace unless namespaces are indented
+ if (!namespaceIndent && !headerStack->empty()
+ && ((*headerStack).back() == &AS_NAMESPACE
+ || (*headerStack).back() == &AS_MODULE)
+ && i == 0) // must be the first brace on the line
+ shouldIndentBracedLine = false;
+
+ if (!tempStacks->empty())
+ {
+ vector<const string*>* temp = tempStacks->back();
+ tempStacks->pop_back();
+ delete temp;
+ }
+ }
+
+ ch = ' '; // needed due to cases such as '}else{', so that headers ('else' in this case) will be identified...
+ } // ch == '}'
+
+ /*
+ * Create a temporary snapshot of the current block's header-list in the
+ * uppermost inner stack in tempStacks, and clear the headerStack up to
+ * the beginning of the block.
+ * Thus, the next future statement will think it comes one indent past
+ * the block's '{' unless it specifically checks for a companion-header
+ * (such as a previous 'if' for an 'else' header) within the tempStacks,
+ * and recreates the temporary snapshot by manipulating the tempStacks.
+ */
+ if (!tempStacks->back()->empty())
+ while (!tempStacks->back()->empty())
+ tempStacks->back()->pop_back();
+ while (!headerStack->empty() && headerStack->back() != &AS_OPEN_BRACE)
+ {
+ tempStacks->back()->emplace_back(headerStack->back());
+ headerStack->pop_back();
+ }
+
+ if (parenDepth == 0 && ch == ';')
+ isContinuation = false;
+
+ if (isInObjCMethodDefinition)
+ {
+ objCColonAlignSubsequent = 0;
+ isImmediatelyPostObjCMethodDefinition = true;
+ }
+
+ previousLastLineHeader = nullptr;
+ isInClassHeader = false; // for 'friend' class
+ isInEnum = false;
+ isInEnumTypeID = false;
+ isInQuestion = false;
+ isInTemplate = false;
+ isInObjCInterface = false;
+ foundPreCommandHeader = false;
+ foundPreCommandMacro = false;
+ squareBracketCount = 0;
+
+ continue;
+ }
+
+ if (isPotentialHeader)
+ {
+ // check for preBlockStatements in C/C++ ONLY if not within parentheses
+ // (otherwise 'struct XXX' statements would be wrongly interpreted...)
+ if (!isInTemplate && !(isCStyle() && parenDepth > 0))
+ {
+ const string* newHeader = findHeader(line, i, preBlockStatements);
+ // handle CORBA IDL module
+ if (newHeader == &AS_MODULE)
+ {
+ char nextChar = peekNextChar(line, i + newHeader->length() - 1);
+ if (prevNonSpaceCh == ')' || !isalpha(nextChar))
+ newHeader = nullptr;
+ }
+ if (newHeader != nullptr
+ && !(isCStyle() && newHeader == &AS_CLASS && isInEnum)) // is not 'enum class'
+ {
+ if (!isSharpStyle())
+ headerStack->emplace_back(newHeader);
+ // do not need 'where' in the headerStack
+ // do not need second 'class' statement in a row
+ else if (!(newHeader == &AS_WHERE
+ || ((newHeader == &AS_CLASS || newHeader == &AS_STRUCT)
+ && !headerStack->empty()
+ && (headerStack->back() == &AS_CLASS
+ || headerStack->back() == &AS_STRUCT))))
+ headerStack->emplace_back(newHeader);
+
+ if (!headerStack->empty())
+ {
+ if ((*headerStack).back() == &AS_CLASS
+ || (*headerStack).back() == &AS_STRUCT
+ || (*headerStack).back() == &AS_INTERFACE)
+ {
+ isInClassHeader = true;
+ }
+ else if ((*headerStack).back() == &AS_NAMESPACE
+ || (*headerStack).back() == &AS_MODULE)
+ {
+ // remove continuationIndent from namespace
+ if (!continuationIndentStack->empty())
+ continuationIndentStack->pop_back();
+ isContinuation = false;
+ }
+ }
+
+ i += newHeader->length() - 1;
+ continue;
+ }
+ }
+ const string* foundIndentableHeader = findHeader(line, i, indentableHeaders);
+
+ if (foundIndentableHeader != nullptr)
+ {
+ // must bypass the header before registering the in statement
+ i += foundIndentableHeader->length() - 1;
+ if (!isInOperator && !isInTemplate && !isNonInStatementArray)
+ {
+ registerContinuationIndent(line, i, spaceIndentCount, tabIncrementIn, 0, false);
+ isContinuation = true;
+ }
+ continue;
+ }
+
+ if (isCStyle() && findKeyword(line, i, AS_OPERATOR))
+ isInOperator = true;
+
+ if (g_preprocessorCppExternCBrace == 1 && findKeyword(line, i, AS_EXTERN))
+ ++g_preprocessorCppExternCBrace;
+
+ if (g_preprocessorCppExternCBrace == 3) // extern "C" is not followed by a '{'
+ g_preprocessorCppExternCBrace = 0;
+
+ // "new" operator is a pointer, not a calculation
+ if (findKeyword(line, i, AS_NEW))
+ {
+ if (isContinuation && !continuationIndentStack->empty() && prevNonSpaceCh == '=')
+ continuationIndentStack->back() = 0;
+ }
+
+ if (isCStyle())
+ {
+ if (findKeyword(line, i, AS_ASM)
+ || findKeyword(line, i, AS__ASM__))
+ {
+ isInAsm = true;
+ }
+ else if (findKeyword(line, i, AS_MS_ASM) // microsoft specific
+ || findKeyword(line, i, AS_MS__ASM))
+ {
+ int index = 4;
+ if (peekNextChar(line, i) == '_') // check for __asm
+ index = 5;
+
+ char peekedChar = peekNextChar(line, i + index);
+ if (peekedChar == '{' || peekedChar == ' ')
+ isInAsmBlock = true;
+ else
+ isInAsmOneLine = true;
+ }
+ }
+
+ // bypass the entire name for all others
+ string name = getCurrentWord(line, i);
+ i += name.length() - 1;
+ continue;
+ }
+
+ // Handle Objective-C statements
+
+ if (ch == '@' && !isWhiteSpace(line[i + 1])
+ && isCharPotentialHeader(line, i + 1))
+ {
+ string curWord = getCurrentWord(line, i + 1);
+ if (curWord == AS_INTERFACE && headerStack->empty())
+ {
+ isInObjCInterface = true;
+ string name = '@' + curWord;
+ i += name.length() - 1;
+ continue;
+ }
+ else if (isInObjCInterface)
+ {
+ --indentCount;
+ isInObjCInterface = false;
+ }
+
+ if (curWord == AS_PUBLIC
+ || curWord == AS_PRIVATE
+ || curWord == AS_PROTECTED)
+ {
+ --indentCount;
+ if (modifierIndent)
+ spaceIndentCount += (indentLength / 2);
+ string name = '@' + curWord;
+ i += name.length() - 1;
+ continue;
+ }
+ else if (curWord == AS_END)
+ {
+ popLastContinuationIndent();
+ spaceIndentCount = 0;
+ isInObjCMethodDefinition = false;
+ string name = '@' + curWord;
+ i += name.length() - 1;
+ continue;
+ }
+ }
+ else if ((ch == '-' || ch == '+')
+ && peekNextChar(line, i) == '('
+ && headerStack->empty()
+ && line.find_first_not_of(" \t") == i)
+ {
+ if (isInObjCInterface)
+ --indentCount;
+ isInObjCInterface = false;
+ isInObjCMethodDefinition = true;
+ continue;
+ }
+
+ // Handle operators
+
+ bool isPotentialOperator = isCharPotentialOperator(ch);
+
+ if (isPotentialOperator)
+ {
+ // Check if an operator has been reached.
+ const string* foundAssignmentOp = findOperator(line, i, assignmentOperators);
+ const string* foundNonAssignmentOp = findOperator(line, i, nonAssignmentOperators);
+
+ if (foundNonAssignmentOp != nullptr)
+ {
+ if (foundNonAssignmentOp == &AS_LAMBDA)
+ foundPreCommandHeader = true;
+ if (isInTemplate && foundNonAssignmentOp == &AS_GR_GR)
+ foundNonAssignmentOp = nullptr;
+ }
+
+ // Since findHeader's boundary checking was not used above, it is possible
+ // that both an assignment op and a non-assignment op where found,
+ // e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the
+ // found operator.
+ if (foundAssignmentOp != nullptr && foundNonAssignmentOp != nullptr)
+ {
+ if (foundAssignmentOp->length() < foundNonAssignmentOp->length())
+ foundAssignmentOp = nullptr;
+ else
+ foundNonAssignmentOp = nullptr;
+ }
+
+ if (foundNonAssignmentOp != nullptr)
+ {
+ if (foundNonAssignmentOp->length() > 1)
+ i += foundNonAssignmentOp->length() - 1;
+
+ // 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
+ && continuationIndentStack->empty()
+ && isCStyle()
+ && (foundNonAssignmentOp == &AS_GR_GR
+ || foundNonAssignmentOp == &AS_LS_LS))
+ {
+ // this will be true if the line begins with the operator
+ if (i < 2 && spaceIndentCount == 0)
+ spaceIndentCount += 2 * indentLength;
+ // align to the beginning column of the operator
+ registerContinuationIndent(line, i - foundNonAssignmentOp->length(), spaceIndentCount, tabIncrementIn, 0, false);
+ }
+ }
+
+ else if (foundAssignmentOp != nullptr)
+ {
+ foundPreCommandHeader = false; // clears this for array assignments
+ foundPreCommandMacro = false;
+
+ if (foundAssignmentOp->length() > 1)
+ i += foundAssignmentOp->length() - 1;
+
+ 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 = getContinuationIndentAssign(line, i);
+ int continuationIndentCount = prevWordIndex + spaceIndentCount + tabIncrementIn;
+ continuationIndentStack->emplace_back(continuationIndentCount);
+ isContinuation = true;
+ }
+ }
+ // don't indent an assignment if 'let'
+ else if (isInLet)
+ {
+ isInLet = false;
+ }
+ else if (!lineBeginsWithComma)
+ {
+ if (i == 0 && spaceIndentCount == 0)
+ spaceIndentCount += indentLength;
+ registerContinuationIndent(line, i, spaceIndentCount, tabIncrementIn, 0, false);
+ isContinuation = true;
+ }
+ }
+ }
+ }
+ } // end of for loop * end of for loop * end of for loop * end of for loop * end of for loop *
+}
+
+} // end namespace astyle