#include "astyle.h"
#include <algorithm>
#include <fstream>
namespace astyle {
ASFormatter::ASFormatter()
{
sourceIterator = nullptr;
enhancer = new ASEnhancer;
preBraceHeaderStack = nullptr;
braceTypeStack = nullptr;
parenStack = nullptr;
structStack = nullptr;
questionMarkStack = nullptr;
lineCommentNoIndent = false;
formattingStyle = STYLE_NONE;
braceFormatMode = NONE_MODE;
pointerAlignment = PTR_ALIGN_NONE;
referenceAlignment = REF_SAME_AS_PTR;
objCColonPadMode = COLON_PAD_NO_CHANGE;
lineEnd = LINEEND_DEFAULT;
maxCodeLength = string::npos;
shouldPadCommas = false;
shouldPadOperators = false;
shouldPadParensOutside = false;
shouldPadFirstParen = false;
shouldPadParensInside = false;
shouldPadHeader = false;
shouldStripCommentPrefix = false;
shouldUnPadParens = false;
attachClosingBraceMode = false;
shouldBreakOneLineBlocks = true;
shouldBreakOneLineHeaders = false;
shouldBreakOneLineStatements = true;
shouldConvertTabs = false;
shouldIndentCol1Comments = false;
shouldIndentPreprocBlock = false;
shouldCloseTemplates = false;
shouldAttachExternC = false;
shouldAttachNamespace = false;
shouldAttachClass = false;
shouldAttachClosingWhile = false;
shouldAttachInline = false;
shouldBreakBlocks = false;
shouldBreakClosingHeaderBlocks = false;
shouldBreakClosingHeaderBraces = false;
shouldDeleteEmptyLines = false;
shouldBreakElseIfs = false;
shouldBreakLineAfterLogical = false;
shouldAddBraces = false;
shouldAddOneLineBraces = false;
shouldRemoveBraces = false;
shouldPadMethodColon = false;
shouldPadMethodPrefix = false;
shouldUnPadMethodPrefix = false;
shouldPadReturnType = false;
shouldUnPadReturnType = false;
shouldPadParamType = false;
shouldUnPadParamType = false;
formatterFileType = 9; headers = new vector<const string*>;
nonParenHeaders = new vector<const string*>;
preDefinitionHeaders = new vector<const string*>;
preCommandHeaders = new vector<const string*>;
operators = new vector<const string*>;
assignmentOperators = new vector<const string*>;
castOperators = new vector<const string*>;
indentableMacros = new vector<const pair<const string, const string>* >;
}
ASFormatter::~ASFormatter()
{
deleteContainer(preBraceHeaderStack);
deleteContainer(braceTypeStack);
deleteContainer(parenStack);
deleteContainer(structStack);
deleteContainer(questionMarkStack);
formatterFileType = 9; delete headers;
delete nonParenHeaders;
delete preDefinitionHeaders;
delete preCommandHeaders;
delete operators;
delete assignmentOperators;
delete castOperators;
delete indentableMacros;
ASBeautifier::deleteBeautifierVectors();
delete enhancer;
}
void ASFormatter::init(ASSourceIterator* si)
{
buildLanguageVectors();
fixOptionVariableConflicts();
ASBeautifier::init(si);
sourceIterator = si;
enhancer->init(getFileType(),
getIndentLength(),
getTabLength(),
getIndentString() == "\t",
getForceTabIndentation(),
getNamespaceIndent(),
getCaseIndent(),
shouldIndentPreprocBlock,
getPreprocDefineIndent(),
getEmptyLineFill(),
indentableMacros);
initContainer(preBraceHeaderStack, new vector<const string*>);
initContainer(parenStack, new vector<int>);
initContainer(structStack, new vector<bool>);
initContainer(questionMarkStack, new vector<bool>);
parenStack->emplace_back(0); initContainer(braceTypeStack, new vector<BraceType>);
braceTypeStack->emplace_back(NULL_TYPE); clearFormattedLineSplitPoints();
currentHeader = nullptr;
currentLine = "";
readyFormattedLine = "";
formattedLine = "";
verbatimDelimiter = "";
currentChar = ' ';
previousChar = ' ';
previousCommandChar = ' ';
previousNonWSChar = ' ';
quoteChar = '"';
preprocBlockEnd = 0;
charNum = 0;
checksumIn = 0;
checksumOut = 0;
currentLineFirstBraceNum = string::npos;
formattedLineCommentNum = 0;
leadingSpaces = 0;
previousReadyFormattedLineLength = string::npos;
preprocBraceTypeStackSize = 0;
spacePadNum = 0;
nextLineSpacePadNum = 0;
objCColonAlign = 0;
templateDepth = 0;
squareBracketCount = 0;
runInIndentChars = 0;
tabIncrementIn = 0;
previousBraceType = NULL_TYPE;
isVirgin = true;
isInVirginLine = true;
isInLineComment = false;
isInComment = false;
isInCommentStartLine = false;
noTrimCommentContinuation = false;
isInPreprocessor = false;
isInPreprocessorBeautify = false;
doesLineStartComment = false;
lineEndsInCommentOnly = false;
lineIsCommentOnly = false;
lineIsLineCommentOnly = false;
lineIsEmpty = false;
isImmediatelyPostCommentOnly = false;
isImmediatelyPostEmptyLine = false;
isInClassInitializer = false;
isInQuote = false;
isInVerbatimQuote = false;
haveLineContinuationChar = false;
isInQuoteContinuation = false;
isHeaderInMultiStatementLine = false;
isSpecialChar = false;
isNonParenHeader = false;
foundNamespaceHeader = false;
foundClassHeader = false;
foundStructHeader = false;
foundInterfaceHeader = false;
foundPreDefinitionHeader = false;
foundPreCommandHeader = false;
foundPreCommandMacro = false;
foundTrailingReturnType = false;
foundCastOperator = false;
foundQuestionMark = false;
isInLineBreak = false;
endOfAsmReached = false;
endOfCodeReached = false;
isFormattingModeOff = false;
isInEnum = false;
isInExecSQL = false;
isInAsm = false;
isInAsmOneLine = false;
isInAsmBlock = false;
isLineReady = false;
elseHeaderFollowsComments = false;
caseHeaderFollowsComments = false;
isPreviousBraceBlockRelated = false;
isInPotentialCalculation = false;
needHeaderOpeningBrace = false;
shouldBreakLineAtNextChar = false;
shouldKeepLineUnbroken = false;
shouldReparseCurrentChar = false;
passedSemicolon = false;
passedColon = false;
isImmediatelyPostNonInStmt = false;
isCharImmediatelyPostNonInStmt = false;
isInTemplate = false;
isImmediatelyPostComment = false;
isImmediatelyPostLineComment = false;
isImmediatelyPostEmptyBlock = false;
isImmediatelyPostObjCMethodPrefix = false;
isImmediatelyPostPreprocessor = false;
isImmediatelyPostReturn = false;
isImmediatelyPostThrow = false;
isImmediatelyPostNewDelete = false;
isImmediatelyPostOperator = false;
isImmediatelyPostTemplate = false;
isImmediatelyPostPointerOrReference = false;
isCharImmediatelyPostReturn = false;
isCharImmediatelyPostThrow = false;
isCharImmediatelyPostNewDelete = false;
isCharImmediatelyPostOperator = false;
isCharImmediatelyPostComment = false;
isPreviousCharPostComment = false;
isCharImmediatelyPostLineComment = false;
isCharImmediatelyPostOpenBlock = false;
isCharImmediatelyPostCloseBlock = false;
isCharImmediatelyPostTemplate = false;
isCharImmediatelyPostPointerOrReference = false;
isInObjCInterface = false;
isInObjCMethodDefinition = false;
isInObjCReturnType = false;
isInObjCSelector = false;
breakCurrentOneLineBlock = false;
shouldRemoveNextClosingBrace = false;
isInBraceRunIn = false;
currentLineBeginsWithBrace = false;
isPrependPostBlockEmptyLineRequested = false;
isAppendPostBlockEmptyLineRequested = false;
isIndentableProprocessor = false;
isIndentableProprocessorBlock = false;
prependEmptyLine = false;
appendOpeningBrace = false;
foundClosingHeader = false;
isImmediatelyPostHeader = false;
isInHeader = false;
isInCase = false;
isFirstPreprocConditional = false;
processedFirstConditional = false;
isJavaStaticConstructor = false;
}
void ASFormatter::buildLanguageVectors()
{
if (getFileType() == formatterFileType) return;
formatterFileType = getFileType();
headers->clear();
nonParenHeaders->clear();
preDefinitionHeaders->clear();
preCommandHeaders->clear();
operators->clear();
assignmentOperators->clear();
castOperators->clear();
indentableMacros->clear();
ASResource::buildHeaders(headers, getFileType());
ASResource::buildNonParenHeaders(nonParenHeaders, getFileType());
ASResource::buildPreDefinitionHeaders(preDefinitionHeaders, getFileType());
ASResource::buildPreCommandHeaders(preCommandHeaders, getFileType());
ASResource::buildOperators(operators, getFileType());
ASResource::buildAssignmentOperators(assignmentOperators);
ASResource::buildCastOperators(castOperators);
ASResource::buildIndentableMacros(indentableMacros); }
void ASFormatter::fixOptionVariableConflicts()
{
if (formattingStyle == STYLE_ALLMAN)
{
setBraceFormatMode(BREAK_MODE);
}
else if (formattingStyle == STYLE_JAVA)
{
setBraceFormatMode(ATTACH_MODE);
}
else if (formattingStyle == STYLE_KR)
{
setBraceFormatMode(LINUX_MODE);
}
else if (formattingStyle == STYLE_STROUSTRUP)
{
setBraceFormatMode(LINUX_MODE);
setBreakClosingHeaderBracesMode(true);
}
else if (formattingStyle == STYLE_WHITESMITH)
{
setBraceFormatMode(BREAK_MODE);
setBraceIndent(true);
setClassIndent(true); setSwitchIndent(true); }
else if (formattingStyle == STYLE_VTK)
{
setBraceFormatMode(BREAK_MODE);
setBraceIndentVtk(true); setSwitchIndent(true); }
else if (formattingStyle == STYLE_BANNER)
{
setBraceFormatMode(ATTACH_MODE);
setBraceIndent(true);
setClassIndent(true); setSwitchIndent(true); }
else if (formattingStyle == STYLE_GNU)
{
setBraceFormatMode(BREAK_MODE);
setBlockIndent(true);
}
else if (formattingStyle == STYLE_LINUX)
{
setBraceFormatMode(LINUX_MODE);
setMinConditionalIndentOption(MINCOND_ONEHALF);
}
else if (formattingStyle == STYLE_HORSTMANN)
{
setBraceFormatMode(RUN_IN_MODE);
setSwitchIndent(true);
}
else if (formattingStyle == STYLE_1TBS)
{
setBraceFormatMode(LINUX_MODE);
setAddBracesMode(true);
setRemoveBracesMode(false);
}
else if (formattingStyle == STYLE_GOOGLE)
{
setBraceFormatMode(ATTACH_MODE);
setModifierIndent(true);
setClassIndent(false);
}
else if (formattingStyle == STYLE_MOZILLA)
{
setBraceFormatMode(LINUX_MODE);
}
else if (formattingStyle == STYLE_PICO)
{
setBraceFormatMode(RUN_IN_MODE);
setAttachClosingBraceMode(true);
setSwitchIndent(true);
setBreakOneLineBlocksMode(false);
setBreakOneLineStatementsMode(false);
if (shouldAddBraces)
shouldAddOneLineBraces = true;
}
else if (formattingStyle == STYLE_LISP)
{
setBraceFormatMode(ATTACH_MODE);
setAttachClosingBraceMode(true);
setBreakOneLineStatementsMode(false);
if (shouldAddOneLineBraces)
{
shouldAddBraces = true;
shouldAddOneLineBraces = false;
}
}
setMinConditionalIndentLength();
if (getTabLength() == 0)
setDefaultTabLength();
if (shouldAddOneLineBraces)
setBreakOneLineBlocksMode(false);
if (shouldAddBraces || shouldAddOneLineBraces)
setRemoveBracesMode(false);
if (getClassIndent())
setModifierIndent(false);
}
string ASFormatter::nextLine()
{
const string* newHeader = nullptr;
isInVirginLine = isVirgin;
isCharImmediatelyPostComment = false;
isPreviousCharPostComment = false;
isCharImmediatelyPostLineComment = false;
isCharImmediatelyPostOpenBlock = false;
isCharImmediatelyPostCloseBlock = false;
isCharImmediatelyPostTemplate = false;
while (!isLineReady)
{
if (shouldReparseCurrentChar)
shouldReparseCurrentChar = false;
else if (!getNextChar())
{
breakLine();
continue;
}
else {
if (isInVirginLine && currentChar == '{'
&& currentLineBeginsWithBrace
&& previousCommandChar == ' ')
previousCommandChar = '{';
if (isInClassInitializer
&& isBraceType(braceTypeStack->back(), COMMAND_TYPE))
isInClassInitializer = false;
if (isInBraceRunIn)
isInLineBreak = false;
if (!isWhiteSpace(currentChar))
isInBraceRunIn = false;
isPreviousCharPostComment = isCharImmediatelyPostComment;
isCharImmediatelyPostComment = false;
isCharImmediatelyPostTemplate = false;
isCharImmediatelyPostReturn = false;
isCharImmediatelyPostThrow = false;
isCharImmediatelyPostNewDelete = false;
isCharImmediatelyPostOperator = false;
isCharImmediatelyPostPointerOrReference = false;
isCharImmediatelyPostOpenBlock = false;
isCharImmediatelyPostCloseBlock = false;
}
if ((lineIsLineCommentOnly || lineIsCommentOnly)
&& currentLine.find("*INDENT-ON*", charNum) != string::npos
&& isFormattingModeOff)
{
isFormattingModeOff = false;
breakLine();
formattedLine = currentLine;
charNum = (int) currentLine.length() - 1;
continue;
}
if (isFormattingModeOff)
{
breakLine();
formattedLine = currentLine;
charNum = (int) currentLine.length() - 1;
continue;
}
if ((lineIsLineCommentOnly || lineIsCommentOnly)
&& currentLine.find("*INDENT-OFF*", charNum) != string::npos)
{
isFormattingModeOff = true;
if (isInLineBreak) breakLine();
formattedLine = currentLine;
charNum = (int)currentLine.length() - 1;
continue;
}
if (shouldBreakLineAtNextChar)
{
if (isWhiteSpace(currentChar) && !lineIsEmpty)
continue;
isInLineBreak = true;
shouldBreakLineAtNextChar = false;
}
if (isInExecSQL && !passedSemicolon)
{
if (currentChar == ';')
passedSemicolon = true;
appendCurrentChar();
continue;
}
if (isInLineComment)
{
formatLineCommentBody();
continue;
}
else if (isInComment)
{
formatCommentBody();
continue;
}
else if (isInQuote)
{
formatQuoteBody();
continue;
}
if (isSequenceReached("//"))
{
formatLineCommentOpener();
testForTimeToSplitFormattedLine();
continue;
}
else if (isSequenceReached("/*"))
{
formatCommentOpener();
testForTimeToSplitFormattedLine();
continue;
}
else if (currentChar == '"'
|| (currentChar == '\'' && !isDigitSeparator(currentLine, charNum)))
{
formatQuoteOpener();
testForTimeToSplitFormattedLine();
continue;
}
else if (currentChar == '#'
&& currentLine.find_first_not_of(" \t") == (size_t) charNum)
{
string preproc = trim(currentLine.c_str() + charNum + 1);
if (preproc.length() > 0
&& isCharPotentialHeader(preproc, 0)
&& (findKeyword(preproc, 0, "region")
|| findKeyword(preproc, 0, "endregion")
|| findKeyword(preproc, 0, "error")
|| findKeyword(preproc, 0, "warning")
|| findKeyword(preproc, 0, "line")))
{
currentLine = rtrim(currentLine); if (formattedLine.length() > 0 && formattedLine[0] == '{')
{
isInLineBreak = true;
isInBraceRunIn = false;
}
if (previousCommandChar == '}')
currentHeader = nullptr;
isInLineComment = true;
appendCurrentChar();
continue;
}
}
if (isInPreprocessor)
{
appendCurrentChar();
continue;
}
if (isInTemplate && shouldCloseTemplates)
{
if (previousNonWSChar == '>' && isWhiteSpace(currentChar) && peekNextChar() == '>')
continue;
}
if (shouldRemoveNextClosingBrace && currentChar == '}')
{
currentLine[charNum] = currentChar = ' ';
shouldRemoveNextClosingBrace = false;
assert(adjustChecksumIn(-'}'));
if (isEmptyLine(currentLine))
continue;
}
if (isWhiteSpace(currentChar))
{
appendCurrentChar();
continue;
}
if (currentChar == '#')
{
isInPreprocessor = true;
if (formattedLine.length() > 0 && formattedLine[0] == '{')
{
isInLineBreak = true;
isInBraceRunIn = false;
}
processPreprocessor();
if (shouldIndentPreprocBlock
&& (isBraceType(braceTypeStack->back(), NULL_TYPE)
|| isBraceType(braceTypeStack->back(), NAMESPACE_TYPE))
&& !foundClassHeader
&& !isInClassInitializer
&& sourceIterator->tellg() > preprocBlockEnd)
{
string preproc = ASBeautifier::extractPreprocessorStatement(currentLine);
if (preproc.length() >= 2 && preproc.substr(0, 2) == "if") {
if (isImmediatelyPostPreprocessor)
breakLine();
isIndentableProprocessorBlock = isIndentablePreprocessorBlock(currentLine, charNum);
isIndentableProprocessor = isIndentableProprocessorBlock;
}
}
if (isIndentableProprocessorBlock
&& charNum < (int) currentLine.length() - 1
&& isWhiteSpace(currentLine[charNum + 1]))
{
size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
if (nextText != string::npos)
currentLine.erase(charNum + 1, nextText - charNum - 1);
}
if (isIndentableProprocessorBlock
&& sourceIterator->tellg() >= preprocBlockEnd)
isIndentableProprocessorBlock = false;
}
if (isImmediatelyPostComment)
{
caseHeaderFollowsComments = false;
isImmediatelyPostComment = false;
isCharImmediatelyPostComment = true;
}
if (isImmediatelyPostLineComment)
{
caseHeaderFollowsComments = false;
isImmediatelyPostLineComment = false;
isCharImmediatelyPostLineComment = true;
}
if (isImmediatelyPostReturn)
{
isImmediatelyPostReturn = false;
isCharImmediatelyPostReturn = true;
}
if (isImmediatelyPostThrow)
{
isImmediatelyPostThrow = false;
isCharImmediatelyPostThrow = true;
}
if (isImmediatelyPostNewDelete)
{
isImmediatelyPostNewDelete = false;
isCharImmediatelyPostNewDelete = true;
}
if (isImmediatelyPostOperator)
{
isImmediatelyPostOperator = false;
isCharImmediatelyPostOperator = true;
}
if (isImmediatelyPostTemplate)
{
isImmediatelyPostTemplate = false;
isCharImmediatelyPostTemplate = true;
}
if (isImmediatelyPostPointerOrReference)
{
isImmediatelyPostPointerOrReference = false;
isCharImmediatelyPostPointerOrReference = true;
}
if (isImmediatelyPostHeader)
{
if (currentChar != '{'
&& shouldAddBraces
&& (shouldBreakOneLineStatements || !isHeaderInMultiStatementLine)
&& isOkToBreakBlock(braceTypeStack->back()))
{
bool bracesAdded = addBracesToStatement();
if (bracesAdded && !shouldAddOneLineBraces)
{
size_t firstText = currentLine.find_first_not_of(" \t");
assert(firstText != string::npos);
if ((int) firstText == charNum || shouldBreakOneLineHeaders)
breakCurrentOneLineBlock = true;
}
}
else if (currentChar == '{' && shouldRemoveBraces)
{
bool bracesRemoved = removeBracesFromStatement();
if (bracesRemoved)
{
shouldRemoveNextClosingBrace = true;
if (isBeforeAnyLineEndComment(charNum))
spacePadNum--;
else if (shouldBreakOneLineBlocks
|| (currentLineBeginsWithBrace
&& currentLine.find_first_not_of(" \t") != string::npos))
shouldBreakLineAtNextChar = true;
continue;
}
}
if (shouldBreakElseIfs
&& currentHeader == &AS_ELSE
&& isOkToBreakBlock(braceTypeStack->back())
&& !isBeforeAnyComment()
&& (shouldBreakOneLineStatements || !isHeaderInMultiStatementLine))
{
string nextText = peekNextText(currentLine.substr(charNum));
if (nextText.length() > 0
&& isCharPotentialHeader(nextText, 0)
&& ASBase::findHeader(nextText, 0, headers) == &AS_IF)
{
isInLineBreak = true;
}
}
if (shouldBreakOneLineHeaders
&& peekNextChar() != ' '
&& (shouldBreakOneLineStatements
|| (!isHeaderInMultiStatementLine
&& !isMultiStatementLine()))
&& isOkToBreakBlock(braceTypeStack->back())
&& !isBeforeAnyComment())
{
if (currentChar == '{')
{
if (!currentLineBeginsWithBrace)
{
if (isOneLineBlockReached(currentLine, charNum) == 3)
isInLineBreak = false;
else
breakCurrentOneLineBlock = true;
}
}
else if (currentHeader == &AS_ELSE)
{
string nextText = peekNextText(currentLine.substr(charNum), true);
if (nextText.length() > 0
&& ((isCharPotentialHeader(nextText, 0)
&& ASBase::findHeader(nextText, 0, headers) != &AS_IF)
|| nextText[0] == '{'))
isInLineBreak = true;
}
else
{
isInLineBreak = true;
}
}
isImmediatelyPostHeader = false;
}
if (passedSemicolon) {
passedSemicolon = false;
if (parenStack->back() == 0 && !isCharImmediatelyPostComment && currentChar != ';') {
if (isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE))
{
size_t blockEnd = currentLine.rfind(AS_CLOSE_BRACE);
assert(blockEnd != string::npos);
if (isBeforeAnyLineEndComment(blockEnd))
{
size_t commentStart = currentLine.find_first_not_of(" \t", blockEnd + 1);
assert(commentStart != string::npos);
assert((currentLine.compare(commentStart, 2, "//") == 0)
|| (currentLine.compare(commentStart, 2, "/*") == 0));
formattedLine.append(getIndentLength() - 1, ' ');
int charNumSave = charNum;
charNum = commentStart;
while (charNum < (int) currentLine.length())
{
currentChar = currentLine[charNum];
if (currentChar == '\t' && shouldConvertTabs)
convertTabToSpaces();
formattedLine.append(1, currentChar);
++charNum;
}
size_t commentLength = currentLine.length() - commentStart;
currentLine.erase(commentStart, commentLength);
charNum = charNumSave;
currentChar = currentLine[charNum];
testForTimeToSplitFormattedLine();
}
}
isInExecSQL = false;
shouldReparseCurrentChar = true;
if (formattedLine.find_first_not_of(" \t") != string::npos)
isInLineBreak = true;
if (needHeaderOpeningBrace)
{
isCharImmediatelyPostCloseBlock = true;
needHeaderOpeningBrace = false;
}
continue;
}
}
if (passedColon)
{
passedColon = false;
if (parenStack->back() == 0
&& !isBeforeAnyComment()
&& (formattedLine.find_first_not_of(" \t") != string::npos))
{
shouldReparseCurrentChar = true;
isInLineBreak = true;
continue;
}
}
if (!isInTemplate && currentChar == '<')
{
checkIfTemplateOpener();
}
if (currentChar == '(' || currentChar == '[' || (isInTemplate && currentChar == '<'))
{
questionMarkStack->push_back(foundQuestionMark);
foundQuestionMark = false;
parenStack->back()++;
if (currentChar == '[')
{
++squareBracketCount;
if (getAlignMethodColon() && squareBracketCount == 1 && isCStyle())
objCColonAlign = findObjCColonAlignment();
}
}
else if (currentChar == ')' || currentChar == ']' || (isInTemplate && currentChar == '>'))
{
foundPreCommandHeader = false;
parenStack->back()--;
if (parenStack->back() < 0)
parenStack->back() = 0;
if (!questionMarkStack->empty())
{
foundQuestionMark = questionMarkStack->back();
questionMarkStack->pop_back();
}
if (isInTemplate && currentChar == '>')
{
templateDepth--;
if (templateDepth == 0)
{
isInTemplate = false;
isImmediatelyPostTemplate = true;
}
}
if (isInHeader && parenStack->back() == 0)
{
isInHeader = false;
isImmediatelyPostHeader = true;
foundQuestionMark = false;
}
if (currentChar == ']')
{
--squareBracketCount;
if (squareBracketCount <= 0)
{
squareBracketCount = 0;
objCColonAlign = 0;
}
}
if (currentChar == ')')
{
foundCastOperator = false;
if (parenStack->back() == 0)
endOfAsmReached = true;
}
}
if (currentChar == '{' || currentChar == '}')
{
if (currentChar == '{' && !appendOpeningBrace)
{
BraceType newBraceType = getBraceType();
breakCurrentOneLineBlock = false;
foundNamespaceHeader = false;
foundClassHeader = false;
foundStructHeader = false;
foundInterfaceHeader = false;
foundPreDefinitionHeader = false;
foundPreCommandHeader = false;
foundPreCommandMacro = false;
foundTrailingReturnType = false;
isInPotentialCalculation = false;
isInObjCMethodDefinition = false;
isInObjCInterface = false;
isInEnum = false;
isJavaStaticConstructor = false;
isCharImmediatelyPostNonInStmt = false;
needHeaderOpeningBrace = false;
shouldKeepLineUnbroken = false;
objCColonAlign = 0;
isPreviousBraceBlockRelated = !isBraceType(newBraceType, ARRAY_TYPE);
braceTypeStack->emplace_back(newBraceType);
preBraceHeaderStack->emplace_back(currentHeader);
currentHeader = nullptr;
structStack->push_back(isInIndentableStruct);
if (isBraceType(newBraceType, STRUCT_TYPE) && isCStyle())
isInIndentableStruct = isStructAccessModified(currentLine, charNum);
else
isInIndentableStruct = false;
}
BraceType braceType = braceTypeStack->back();
bool isOpeningArrayBrace = (isBraceType(braceType, ARRAY_TYPE)
&& braceTypeStack->size() >= 2
&& !isBraceType((*braceTypeStack)[braceTypeStack->size() - 2], ARRAY_TYPE)
);
if (currentChar == '}')
{
isAppendPostBlockEmptyLineRequested = false;
if (isInAsm)
endOfAsmReached = true;
isInAsmOneLine = isInQuote = false;
shouldKeepLineUnbroken = false;
squareBracketCount = 0;
if (braceTypeStack->size() > 1)
{
previousBraceType = braceTypeStack->back();
braceTypeStack->pop_back();
isPreviousBraceBlockRelated = !isBraceType(braceType, ARRAY_TYPE);
}
else
{
previousBraceType = NULL_TYPE;
isPreviousBraceBlockRelated = false;
}
if (!preBraceHeaderStack->empty())
{
currentHeader = preBraceHeaderStack->back();
preBraceHeaderStack->pop_back();
}
else
currentHeader = nullptr;
if (!structStack->empty())
{
isInIndentableStruct = structStack->back();
structStack->pop_back();
}
else
isInIndentableStruct = false;
if (isNonInStatementArray
&& (!isBraceType(braceTypeStack->back(), ARRAY_TYPE) || peekNextChar() == ';')) isImmediatelyPostNonInStmt = true;
if (!shouldBreakOneLineStatements
&& ASBeautifier::getNextWord(currentLine, charNum) == AS_ELSE)
{
size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
if (ASBeautifier::peekNextChar(currentLine, nextText + 3) == ' ')
shouldBreakLineAtNextChar = true;
}
}
appendOpeningBrace = false;
if (isBraceType(braceType, ARRAY_TYPE))
{
formatArrayBraces(braceType, isOpeningArrayBrace);
}
else
{
if (currentChar == '{')
formatOpeningBrace(braceType);
else
formatClosingBrace(braceType);
}
continue;
}
if ((((previousCommandChar == '{' && isPreviousBraceBlockRelated)
|| ((previousCommandChar == '}'
&& !isImmediatelyPostEmptyBlock
&& isPreviousBraceBlockRelated
&& !isPreviousCharPostComment && peekNextChar() != ' '
&& !isBraceType(previousBraceType, DEFINITION_TYPE))
&& !isBraceType(braceTypeStack->back(), DEFINITION_TYPE)))
&& isOkToBreakBlock(braceTypeStack->back()))
|| (previousCommandChar == '{' && isBraceType(braceTypeStack->back(), ARRAY_TYPE)
&& !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
&& isNonInStatementArray)
|| (formattingStyle == STYLE_PICO
&& (previousCommandChar == '{' && isPreviousBraceBlockRelated)
&& isBraceType(braceTypeStack->back(), COMMAND_TYPE)
&& isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
&& braceFormatMode == RUN_IN_MODE)
)
{
isCharImmediatelyPostOpenBlock = (previousCommandChar == '{');
isCharImmediatelyPostCloseBlock = (previousCommandChar == '}');
if (isCharImmediatelyPostOpenBlock
&& !isCharImmediatelyPostComment
&& !isCharImmediatelyPostLineComment)
{
previousCommandChar = ' ';
if (braceFormatMode == NONE_MODE)
{
if (isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
&& (isBraceType(braceTypeStack->back(), BREAK_BLOCK_TYPE)
|| shouldBreakOneLineBlocks))
isInLineBreak = true;
else if (currentLineBeginsWithBrace)
formatRunIn();
else
breakLine();
}
else if (braceFormatMode == RUN_IN_MODE
&& currentChar != '#')
formatRunIn();
else
isInLineBreak = true;
}
else if (isCharImmediatelyPostCloseBlock
&& shouldBreakOneLineStatements
&& !isCharImmediatelyPostComment
&& ((isLegalNameChar(currentChar) && currentChar != '.')
|| currentChar == '+'
|| currentChar == '-'
|| currentChar == '*'
|| currentChar == '&'
|| currentChar == '('))
{
previousCommandChar = ' ';
isInLineBreak = true;
}
}
isImmediatelyPostEmptyBlock = false;
bool isPotentialHeader = isCharPotentialHeader(currentLine, charNum);
if (isPotentialHeader && !isInTemplate && squareBracketCount == 0)
{
isNonParenHeader = false;
foundClosingHeader = false;
newHeader = findHeader(headers);
if (isCStyle()
&& (newHeader == &AS_FOREVER || newHeader == &AS_FOREACH))
{
if (currentLine.find_first_of("=;", charNum) != string::npos)
newHeader = nullptr;
}
if (isJavaStyle()
&& (newHeader == &AS_SYNCHRONIZED))
{
if (!isBraceType(braceTypeStack->back(), COMMAND_TYPE))
newHeader = nullptr;
}
else if (newHeader == &AS_USING
&& ASBeautifier::peekNextChar(
currentLine, charNum + (*newHeader).length() - 1) != '(')
newHeader = nullptr;
if (newHeader != nullptr)
{
foundClosingHeader = isClosingHeader(newHeader);
if (!foundClosingHeader)
{
if ((newHeader == &AS_WHILE && currentHeader == &AS_DO)
|| (newHeader == &_AS_FINALLY && currentHeader == &_AS_TRY)
|| (newHeader == &_AS_EXCEPT && currentHeader == &_AS_TRY))
foundClosingHeader = true;
else if (isSharpStyle()
&& previousNonWSChar == '}'
&& ((newHeader == &AS_SET && currentHeader == &AS_GET)
|| (newHeader == &AS_REMOVE && currentHeader == &AS_ADD))
&& isOkToBreakBlock(braceTypeStack->back()))
isAppendPostBlockEmptyLineRequested = false;
}
if (isSharpStyle()
&& ((newHeader == &AS_SET && currentHeader == &AS_GET)
|| (newHeader == &AS_REMOVE && currentHeader == &AS_ADD))
&& !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
&& currentLine[currentLine.find_first_not_of(" \t")] == '}')
isInLineBreak = true;
const string* previousHeader = currentHeader;
currentHeader = newHeader;
needHeaderOpeningBrace = true;
if ((previousNonWSChar == ';' || previousNonWSChar == ':')
&& !isInLineBreak
&& isOkToBreakBlock(braceTypeStack->back()))
{
if (maxCodeLength != string::npos
&& previousHeader != &AS_CASE)
isInLineBreak = true;
else
isHeaderInMultiStatementLine = true;
}
if (foundClosingHeader && previousNonWSChar == '}')
{
if (isOkToBreakBlock(braceTypeStack->back()))
isLineBreakBeforeClosingHeader();
if (isInLineBreak)
nextLineSpacePadNum = getNextLineCommentAdjustment();
else
spacePadNum = getCurrentLineCommentAdjustment();
}
isNonParenHeader = findHeader(nonParenHeaders) != nullptr;
if (isNonParenHeader
&& (currentHeader == &AS_CATCH
|| currentHeader == &AS_CASE))
{
int startChar = charNum + currentHeader->length() - 1;
if (ASBeautifier::peekNextChar(currentLine, startChar) == '(')
isNonParenHeader = false;
}
if (currentHeader == &AS_IF
&& previousHeader == &AS_ELSE
&& isInLineBreak
&& !shouldBreakElseIfs
&& !isCharImmediatelyPostLineComment
&& !isImmediatelyPostPreprocessor)
{
size_t start = formattedLine.length() >= 6 ? formattedLine.length() - 6 : 0;
if (formattedLine.find(AS_ELSE, start) != string::npos)
{
appendSpacePad();
isInLineBreak = false;
}
}
appendSequence(*currentHeader);
goForward(currentHeader->length() - 1);
if (shouldPadHeader
&& !isNonParenHeader
&& charNum < (int) currentLine.length() - 1 && !isWhiteSpace(currentLine[charNum + 1]))
appendSpacePad();
if (currentHeader != &AS_CASE && currentHeader != &AS_DEFAULT
&& !(foundClosingHeader && currentHeader == &AS_WHILE))
{
isInHeader = true;
if (isNonParenHeader && !isSharpStyleWithParen(currentHeader))
{
isImmediatelyPostHeader = true;
isInHeader = false;
}
}
if (shouldBreakBlocks
&& isOkToBreakBlock(braceTypeStack->back())
&& !isHeaderInMultiStatementLine)
{
if (previousHeader == nullptr
&& !foundClosingHeader
&& !isCharImmediatelyPostOpenBlock
&& !isImmediatelyPostCommentOnly)
{
isPrependPostBlockEmptyLineRequested = true;
}
if (isClosingHeader(currentHeader)
|| foundClosingHeader)
{
isPrependPostBlockEmptyLineRequested = false;
}
if (shouldBreakClosingHeaderBlocks
&& isCharImmediatelyPostCloseBlock
&& !isImmediatelyPostCommentOnly
&& !(currentHeader == &AS_WHILE && foundClosingHeader))
{
isPrependPostBlockEmptyLineRequested = true;
}
}
if (currentHeader == &AS_CASE
|| currentHeader == &AS_DEFAULT)
isInCase = true;
continue;
}
else if ((newHeader = findHeader(preDefinitionHeaders)) != nullptr
&& parenStack->back() == 0
&& !isInEnum) {
if (newHeader == &AS_NAMESPACE || newHeader == &AS_MODULE)
foundNamespaceHeader = true;
if (newHeader == &AS_CLASS)
foundClassHeader = true;
if (newHeader == &AS_STRUCT)
foundStructHeader = true;
if (newHeader == &AS_INTERFACE)
foundInterfaceHeader = true;
foundPreDefinitionHeader = true;
appendSequence(*newHeader);
goForward(newHeader->length() - 1);
continue;
}
else if ((newHeader = findHeader(preCommandHeaders)) != nullptr)
{
if (previousNonWSChar == ')')
foundPreCommandHeader = true;
}
else if ((newHeader = findHeader(castOperators)) != nullptr)
{
foundCastOperator = true;
appendSequence(*newHeader);
goForward(newHeader->length() - 1);
continue;
}
}
if (isInLineBreak) {
breakLine();
if (isInVirginLine) {
lineCommentNoBeautify = lineCommentNoIndent;
lineCommentNoIndent = false;
if (isImmediatelyPostPreprocessor)
{
isInIndentablePreproc = isIndentableProprocessor;
isIndentableProprocessor = false;
}
}
}
if (previousNonWSChar == '}' || currentChar == ';')
{
if (currentChar == ';')
{
squareBracketCount = 0;
if (((shouldBreakOneLineStatements
|| isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE))
&& isOkToBreakBlock(braceTypeStack->back()))
&& !(attachClosingBraceMode && peekNextChar() == '}'))
{
passedSemicolon = true;
}
else if (!shouldBreakOneLineStatements
&& ASBeautifier::getNextWord(currentLine, charNum) == AS_ELSE)
{
size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
if (ASBeautifier::peekNextChar(currentLine, nextText + 3) == ' ')
passedSemicolon = true;
}
if (shouldBreakBlocks
&& currentHeader != nullptr
&& currentHeader != &AS_CASE
&& currentHeader != &AS_DEFAULT
&& !isHeaderInMultiStatementLine
&& parenStack->back() == 0)
{
isAppendPostBlockEmptyLineRequested = true;
}
}
if (currentChar != ';'
|| (needHeaderOpeningBrace && parenStack->back() == 0))
currentHeader = nullptr;
resetEndOfStatement();
}
if (currentChar == ':'
&& previousChar != ':' && peekNextChar() != ':') {
if (isInCase)
{
isInCase = false;
if (shouldBreakOneLineStatements)
passedColon = true;
}
else if (isCStyle() && isOkToBreakBlock(braceTypeStack->back())
&& shouldBreakOneLineStatements
&& !foundQuestionMark && !foundPreDefinitionHeader && previousCommandChar != ')' && !foundPreCommandHeader && squareBracketCount == 0 && !isInObjCMethodDefinition && !isInObjCInterface && !isInObjCSelector && !isDigit(peekNextChar()) && !isInEnum && !isInAsm && !isInAsmOneLine && !isInAsmBlock) {
passedColon = true;
}
if (isCStyle()
&& shouldPadMethodColon
&& (squareBracketCount > 0 || isInObjCMethodDefinition || isInObjCSelector)
&& !foundQuestionMark) padObjCMethodColon();
if (isInObjCInterface)
{
appendSpacePad();
if ((int) currentLine.length() > charNum + 1
&& !isWhiteSpace(currentLine[charNum + 1]))
currentLine.insert(charNum + 1, " ");
}
if (isClassInitializer())
isInClassInitializer = true;
}
if (currentChar == '?')
foundQuestionMark = true;
if (isPotentialHeader && !isInTemplate)
{
if (findKeyword(currentLine, charNum, AS_NEW)
|| findKeyword(currentLine, charNum, AS_DELETE))
{
isInPotentialCalculation = false;
isImmediatelyPostNewDelete = true;
}
if (findKeyword(currentLine, charNum, AS_RETURN))
{
isInPotentialCalculation = true; isImmediatelyPostReturn = true;
}
if (findKeyword(currentLine, charNum, AS_OPERATOR))
isImmediatelyPostOperator = true;
if (findKeyword(currentLine, charNum, AS_ENUM))
{
size_t firstNum = currentLine.find_first_of("(){},/");
if (firstNum == string::npos
|| currentLine[firstNum] == '{'
|| currentLine[firstNum] == '/')
isInEnum = true;
}
if (isCStyle()
&& findKeyword(currentLine, charNum, AS_THROW)
&& previousCommandChar != ')'
&& !foundPreCommandHeader) isImmediatelyPostThrow = true;
if (isCStyle() && findKeyword(currentLine, charNum, AS_EXTERN) && isExternC())
isInExternC = true;
if (isCStyle() && findKeyword(currentLine, charNum, AS_AUTO)
&& (isBraceType(braceTypeStack->back(), NULL_TYPE)
|| isBraceType(braceTypeStack->back(), NAMESPACE_TYPE)
|| isBraceType(braceTypeStack->back(), CLASS_TYPE)))
foundTrailingReturnType = true;
if (isCStyle() && findKeyword(currentLine, charNum, AS_NS_DURING))
foundPreCommandMacro = true;
if (isCStyle() && findKeyword(currentLine, charNum, AS_NS_HANDLER))
foundPreCommandMacro = true;
if (isCStyle() && isExecSQL(currentLine, charNum))
isInExecSQL = true;
if (isCStyle())
{
if (findKeyword(currentLine, charNum, AS_ASM)
|| findKeyword(currentLine, charNum, AS__ASM__))
{
isInAsm = true;
}
else if (findKeyword(currentLine, charNum, AS_MS_ASM) || findKeyword(currentLine, charNum, AS_MS__ASM))
{
int index = 4;
if (peekNextChar() == '_') index = 5;
char peekedChar = ASBase::peekNextChar(currentLine, charNum + index);
if (peekedChar == '{' || peekedChar == ' ')
isInAsmBlock = true;
else
isInAsmOneLine = true;
}
}
if (isJavaStyle()
&& (findKeyword(currentLine, charNum, AS_STATIC)
&& isNextCharOpeningBrace(charNum + 6)))
isJavaStaticConstructor = true;
if (isSharpStyle()
&& (findKeyword(currentLine, charNum, AS_DELEGATE)
|| findKeyword(currentLine, charNum, AS_UNCHECKED)))
isSharpDelegate = true;
string name = getCurrentWord(currentLine, charNum);
if (name == "and" || name == "or")
{
if (shouldPadOperators && previousNonWSChar != ':')
{
appendSpacePad();
appendOperator(name);
goForward(name.length() - 1);
if (!isBeforeAnyComment()
&& !(currentLine.compare(charNum + 1, 1, AS_SEMICOLON) == 0)
&& !(currentLine.compare(charNum + 1, 2, AS_SCOPE_RESOLUTION) == 0))
appendSpaceAfter();
}
else
{
appendOperator(name);
goForward(name.length() - 1);
}
}
else
{
appendSequence(name);
goForward(name.length() - 1);
}
continue;
}
if (currentChar == '@'
&& isCharPotentialHeader(currentLine, charNum + 1)
&& findKeyword(currentLine, charNum + 1, AS_INTERFACE)
&& isBraceType(braceTypeStack->back(), NULL_TYPE))
{
isInObjCInterface = true;
string name = '@' + AS_INTERFACE;
appendSequence(name);
goForward(name.length() - 1);
continue;
}
else if (currentChar == '@'
&& isCharPotentialHeader(currentLine, charNum + 1)
&& findKeyword(currentLine, charNum + 1, AS_SELECTOR))
{
isInObjCSelector = true;
string name = '@' + AS_SELECTOR;
appendSequence(name);
goForward(name.length() - 1);
continue;
}
else if ((currentChar == '-' || currentChar == '+')
&& (int) currentLine.find_first_not_of(" \t") == charNum
&& peekNextChar() == '('
&& isBraceType(braceTypeStack->back(), NULL_TYPE)
&& !isInPotentialCalculation)
{
isInObjCMethodDefinition = true;
isImmediatelyPostObjCMethodPrefix = true;
isInObjCInterface = false;
if (getAlignMethodColon())
objCColonAlign = findObjCColonAlignment();
appendCurrentChar();
continue;
}
bool isPotentialOperator = isCharPotentialOperator(currentChar);
newHeader = nullptr;
if (isPotentialOperator)
{
newHeader = findOperator(operators);
if (newHeader != nullptr
&& newHeader == &AS_GCC_MIN_ASSIGN
&& isJavaStyle()
&& isInTemplate)
newHeader = nullptr;
if (newHeader != nullptr)
{
if (newHeader == &AS_LAMBDA)
foundPreCommandHeader = true;
if (isInTemplate && (newHeader == &AS_GR_GR || newHeader == &AS_GR_GR_GR))
newHeader = &AS_GR;
if (!isInPotentialCalculation)
{
if (find(begin(*assignmentOperators), end(*assignmentOperators), newHeader)
!= end(*assignmentOperators))
{
foundPreCommandHeader = false;
char peekedChar = peekNextChar();
isInPotentialCalculation = !(newHeader == &AS_EQUAL && peekedChar == '*')
&& !(newHeader == &AS_EQUAL && peekedChar == '&')
&& !isCharImmediatelyPostOperator;
}
}
}
}
if (newHeader != nullptr && !isJavaStyle()
&& (newHeader == &AS_MULT
|| newHeader == &AS_BIT_AND
|| newHeader == &AS_BIT_XOR
|| newHeader == &AS_AND)
&& isPointerOrReference())
{
if (!isDereferenceOrAddressOf() && !isOperatorPaddingDisabled())
formatPointerOrReference();
else
{
appendOperator(*newHeader);
goForward(newHeader->length() - 1);
}
isImmediatelyPostPointerOrReference = true;
continue;
}
if (shouldPadOperators && newHeader != nullptr && !isOperatorPaddingDisabled())
{
padOperators(newHeader);
continue;
}
if (currentChar == ',')
{
const size_t len = formattedLine.length();
size_t lastText = formattedLine.find_last_not_of(' ');
if (lastText != string::npos && lastText < len - 1)
{
formattedLine.resize(lastText + 1);
int size_diff = len - (lastText + 1);
spacePadNum -= size_diff;
}
}
if (currentChar == ';'
|| (currentChar == ',' && (shouldPadOperators || shouldPadCommas)))
{
char nextChar = ' ';
if (charNum + 1 < (int) currentLine.length())
nextChar = currentLine[charNum + 1];
if (!isWhiteSpace(nextChar)
&& nextChar != '}'
&& nextChar != ')'
&& nextChar != ']'
&& nextChar != '>'
&& nextChar != ';'
&& !isBeforeAnyComment()
)
{
appendCurrentChar();
appendSpaceAfter();
continue;
}
}
if (currentChar == '(' || currentChar == ')')
{
if (currentChar == '(')
{
if (shouldPadHeader
&& (isCharImmediatelyPostReturn
|| isCharImmediatelyPostThrow
|| isCharImmediatelyPostNewDelete))
appendSpacePad();
}
if (shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens || shouldPadFirstParen)
padParens();
else
appendCurrentChar();
if (isInObjCMethodDefinition)
{
if (currentChar == '(' && isImmediatelyPostObjCMethodPrefix)
{
if (shouldPadMethodPrefix || shouldUnPadMethodPrefix)
padObjCMethodPrefix();
isImmediatelyPostObjCMethodPrefix = false;
isInObjCReturnType = true;
}
else if (currentChar == ')' && isInObjCReturnType)
{
if (shouldPadReturnType || shouldUnPadReturnType)
padObjCReturnType();
isInObjCReturnType = false;
}
else if (shouldPadParamType || shouldUnPadParamType)
padObjCParamType();
}
continue;
}
if (newHeader != nullptr)
{
appendOperator(*newHeader);
goForward(newHeader->length() - 1);
continue;
}
appendCurrentChar();
}
string beautifiedLine;
size_t readyFormattedLineLength = trim(readyFormattedLine).length();
bool isInNamespace = isBraceType(braceTypeStack->back(), NAMESPACE_TYPE);
if (prependEmptyLine && readyFormattedLineLength > 0
&& previousReadyFormattedLineLength > 0)
{
isLineReady = true; beautifiedLine = beautify("");
previousReadyFormattedLineLength = 0;
enhancer->enhance(beautifiedLine, isInNamespace, isInPreprocessorBeautify, isInBeautifySQL);
}
else {
isLineReady = false;
runInIndentContinuation = runInIndentChars;
beautifiedLine = beautify(readyFormattedLine);
previousReadyFormattedLineLength = readyFormattedLineLength;
if (!lineCommentNoBeautify && !isFormattingModeOff)
enhancer->enhance(beautifiedLine, isInNamespace, isInPreprocessorBeautify, isInBeautifySQL);
runInIndentChars = 0;
lineCommentNoBeautify = lineCommentNoIndent;
lineCommentNoIndent = false;
isInIndentablePreproc = isIndentableProprocessor;
isIndentableProprocessor = false;
isElseHeaderIndent = elseHeaderFollowsComments;
isCaseHeaderCommentIndent = caseHeaderFollowsComments;
objCColonAlignSubsequent = objCColonAlign;
if (isCharImmediatelyPostNonInStmt)
{
isNonInStatementArray = false;
isCharImmediatelyPostNonInStmt = false;
}
isInPreprocessorBeautify = isInPreprocessor; isInBeautifySQL = isInExecSQL; }
prependEmptyLine = false;
assert(computeChecksumOut(beautifiedLine));
return beautifiedLine;
}
bool ASFormatter::hasMoreLines() const
{
return !endOfCodeReached;
}
bool ASFormatter::isBraceType(BraceType a, BraceType b) const
{
if (a == NULL_TYPE || b == NULL_TYPE)
return (a == b);
return ((a & b) == b);
}
void ASFormatter::setFormattingStyle(FormatStyle style)
{
formattingStyle = style;
}
void ASFormatter::setAddBracesMode(bool state)
{
shouldAddBraces = state;
}
void ASFormatter::setAddOneLineBracesMode(bool state)
{
shouldAddBraces = state;
shouldAddOneLineBraces = state;
}
void ASFormatter::setRemoveBracesMode(bool state)
{
shouldRemoveBraces = state;
}
void ASFormatter::setAddBracketsMode(bool state)
{
setAddBracesMode(state);
}
void ASFormatter::setAddOneLineBracketsMode(bool state)
{
setAddOneLineBracesMode(state);
}
void ASFormatter::setRemoveBracketsMode(bool state)
{
setRemoveBracesMode(state);
}
void ASFormatter::setBreakClosingHeaderBracketsMode(bool state)
{
setBreakClosingHeaderBracesMode(state);
}
void ASFormatter::setBraceFormatMode(BraceMode mode)
{
braceFormatMode = mode;
}
void ASFormatter::setBreakAfterMode(bool state)
{
shouldBreakLineAfterLogical = state;
}
void ASFormatter::setBreakClosingHeaderBracesMode(bool state)
{
shouldBreakClosingHeaderBraces = state;
}
void ASFormatter::setBreakElseIfsMode(bool state)
{
shouldBreakElseIfs = state;
}
void ASFormatter::setCommaPaddingMode(bool state)
{
shouldPadCommas = state;
}
void ASFormatter::setMaxCodeLength(int max)
{
maxCodeLength = max;
}
void ASFormatter::setOperatorPaddingMode(bool state)
{
shouldPadOperators = state;
}
void ASFormatter::setParensOutsidePaddingMode(bool state)
{
shouldPadParensOutside = state;
}
void ASFormatter::setParensInsidePaddingMode(bool state)
{
shouldPadParensInside = state;
}
void ASFormatter::setParensFirstPaddingMode(bool state)
{
shouldPadFirstParen = state;
}
void ASFormatter::setParensHeaderPaddingMode(bool state)
{
shouldPadHeader = state;
}
void ASFormatter::setParensUnPaddingMode(bool state)
{
shouldUnPadParens = state;
}
void ASFormatter::setPreprocBlockIndent(bool state)
{
shouldIndentPreprocBlock = state;
}
void ASFormatter::setStripCommentPrefix(bool state)
{
shouldStripCommentPrefix = state;
}
void ASFormatter::setMethodPrefixPaddingMode(bool state)
{
shouldPadMethodPrefix = state;
}
void ASFormatter::setMethodPrefixUnPaddingMode(bool state)
{
shouldUnPadMethodPrefix = state;
}
void ASFormatter::setReturnTypePaddingMode(bool state)
{
shouldPadReturnType = state;
}
void ASFormatter::setReturnTypeUnPaddingMode(bool state)
{
shouldUnPadReturnType = state;
}
void ASFormatter::setParamTypePaddingMode(bool state)
{
shouldPadParamType = state;
}
void ASFormatter::setParamTypeUnPaddingMode(bool state)
{
shouldUnPadParamType = state;
}
void ASFormatter::setObjCColonPaddingMode(ObjCColonPad mode)
{
shouldPadMethodColon = true;
objCColonPadMode = mode;
}
void ASFormatter::setAttachClosingBraceMode(bool state)
{
attachClosingBraceMode = state;
}
void ASFormatter::setAttachClass(bool state)
{
shouldAttachClass = state;
}
void ASFormatter::setAttachExternC(bool state)
{
shouldAttachExternC = state;
}
void ASFormatter::setAttachNamespace(bool state)
{
shouldAttachNamespace = state;
}
void ASFormatter::setAttachInline(bool state)
{
shouldAttachInline = state;
}
void ASFormatter::setAttachClosingWhile(bool state)
{
shouldAttachClosingWhile = state;
}
void ASFormatter::setBreakOneLineBlocksMode(bool state)
{
shouldBreakOneLineBlocks = state;
}
void ASFormatter::setBreakOneLineHeadersMode(bool state)
{
shouldBreakOneLineHeaders = state;
}
void ASFormatter::setBreakOneLineStatementsMode(bool state)
{
shouldBreakOneLineStatements = state;
}
void ASFormatter::setCloseTemplatesMode(bool state)
{
shouldCloseTemplates = state;
}
void ASFormatter::setTabSpaceConversionMode(bool state)
{
shouldConvertTabs = state;
}
void ASFormatter::setIndentCol1CommentsMode(bool state)
{
shouldIndentCol1Comments = state;
}
void ASFormatter::setLineEndFormat(LineEndFormat fmt)
{
lineEnd = fmt;
}
void ASFormatter::setBreakBlocksMode(bool state)
{
shouldBreakBlocks = state;
}
void ASFormatter::setBreakClosingHeaderBlocksMode(bool state)
{
shouldBreakClosingHeaderBlocks = state;
}
void ASFormatter::setDeleteEmptyLinesMode(bool state)
{
shouldDeleteEmptyLines = state;
}
void ASFormatter::setPointerAlignment(PointerAlign alignment)
{
pointerAlignment = alignment;
}
void ASFormatter::setReferenceAlignment(ReferenceAlign alignment)
{
referenceAlignment = alignment;
}
void ASFormatter::goForward(int i)
{
while (--i >= 0)
getNextChar();
}
char ASFormatter::peekNextChar() const
{
char ch = ' ';
size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
if (peekNum == string::npos)
return ch;
ch = currentLine[peekNum];
return ch;
}
bool ASFormatter::isBeforeComment() const
{
bool foundComment = false;
size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
if (peekNum == string::npos)
return foundComment;
foundComment = (currentLine.compare(peekNum, 2, "/*") == 0);
return foundComment;
}
bool ASFormatter::isBeforeAnyComment() const
{
bool foundComment = false;
size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
if (peekNum == string::npos)
return foundComment;
foundComment = (currentLine.compare(peekNum, 2, "/*") == 0
|| currentLine.compare(peekNum, 2, "//") == 0);
return foundComment;
}
bool ASFormatter::isBeforeAnyLineEndComment(int startPos) const
{
bool foundLineEndComment = false;
size_t peekNum = currentLine.find_first_not_of(" \t", startPos + 1);
if (peekNum != string::npos)
{
if (currentLine.compare(peekNum, 2, "//") == 0)
foundLineEndComment = true;
else if (currentLine.compare(peekNum, 2, "/*") == 0)
{
size_t endNum = currentLine.find("*/", peekNum + 2);
if (endNum != string::npos)
{
size_t nextChar = currentLine.find_first_not_of(" \t", endNum + 2);
if (nextChar == string::npos)
foundLineEndComment = true;
}
}
}
return foundLineEndComment;
}
bool ASFormatter::isBeforeMultipleLineEndComments(int startPos) const
{
bool foundMultipleLineEndComment = false;
size_t peekNum = currentLine.find_first_not_of(" \t", startPos + 1);
if (peekNum != string::npos)
{
if (currentLine.compare(peekNum, 2, "/*") == 0)
{
size_t endNum = currentLine.find("*/", peekNum + 2);
if (endNum != string::npos)
{
size_t nextChar = currentLine.find_first_not_of(" \t", endNum + 2);
if (nextChar != string::npos
&& currentLine.compare(nextChar, 2, "//") == 0)
foundMultipleLineEndComment = true;
}
}
}
return foundMultipleLineEndComment;
}
bool ASFormatter::getNextChar()
{
isInLineBreak = false;
previousChar = currentChar;
if (!isWhiteSpace(currentChar))
{
previousNonWSChar = currentChar;
if (!isInComment && !isInLineComment && !isInQuote
&& !isImmediatelyPostComment
&& !isImmediatelyPostLineComment
&& !isInPreprocessor
&& !isSequenceReached("/*")
&& !isSequenceReached("//"))
previousCommandChar = currentChar;
}
if (charNum + 1 < (int) currentLine.length()
&& (!isWhiteSpace(peekNextChar()) || isInComment || isInLineComment))
{
currentChar = currentLine[++charNum];
if (currentChar == '\t' && shouldConvertTabs)
convertTabToSpaces();
return true;
}
return getNextLine();
}
bool ASFormatter::getNextLine(bool emptyLineWasDeleted )
{
if (!sourceIterator->hasMoreLines())
{
endOfCodeReached = true;
return false;
}
if (appendOpeningBrace)
currentLine = "{"; else
{
currentLine = sourceIterator->nextLine(emptyLineWasDeleted);
assert(computeChecksumIn(currentLine));
}
inLineNumber++;
if (endOfAsmReached)
endOfAsmReached = isInAsmBlock = isInAsm = false;
shouldKeepLineUnbroken = false;
isInCommentStartLine = false;
isInCase = false;
isInAsmOneLine = false;
isHeaderInMultiStatementLine = false;
isInQuoteContinuation = isInVerbatimQuote || haveLineContinuationChar;
haveLineContinuationChar = false;
isImmediatelyPostEmptyLine = lineIsEmpty;
previousChar = ' ';
if (currentLine.length() == 0)
currentLine = string(" ");
if (!isVirgin)
isInLineBreak = true;
else
isVirgin = false;
if (isImmediatelyPostNonInStmt)
{
isCharImmediatelyPostNonInStmt = true;
isImmediatelyPostNonInStmt = false;
}
isImmediatelyPostPreprocessor = isInPreprocessor;
if (!isInComment
&& (previousNonWSChar != '\\'
|| isEmptyLine(currentLine)))
isInPreprocessor = false;
if (passedSemicolon)
isInExecSQL = false;
initNewLine();
currentChar = currentLine[charNum];
if (isInBraceRunIn && previousNonWSChar == '{' && !isInComment)
isInLineBreak = false;
isInBraceRunIn = false;
if (currentChar == '\t' && shouldConvertTabs)
convertTabToSpaces();
if (shouldDeleteEmptyLines
&& lineIsEmpty
&& isBraceType((*braceTypeStack)[braceTypeStack->size() - 1], COMMAND_TYPE))
{
if (!shouldBreakBlocks || previousNonWSChar == '{' || !commentAndHeaderFollows())
{
isInPreprocessor = isImmediatelyPostPreprocessor; lineIsEmpty = false;
return getNextLine(true);
}
}
return true;
}
void ASFormatter::initNewLine()
{
size_t len = currentLine.length();
size_t tabSize = getTabLength();
charNum = 0;
if (isInQuoteContinuation
|| (isInPreprocessor && !getPreprocDefineIndent()))
return;
if (isInExecSQL)
{
size_t tabCount_ = 0;
size_t i;
for (i = 0; i < currentLine.length(); i++)
{
if (!isWhiteSpace(currentLine[i])) break;
if (currentLine[i] == '\t')
{
size_t numSpaces = tabSize - ((tabCount_ + i) % tabSize);
currentLine.replace(i, 1, numSpaces, ' ');
tabCount_++;
i += tabSize - 1;
}
}
trimContinuationLine();
return;
}
if (isInComment)
{
if (noTrimCommentContinuation)
leadingSpaces = tabIncrementIn = 0;
trimContinuationLine();
return;
}
isImmediatelyPostCommentOnly = lineIsLineCommentOnly || lineEndsInCommentOnly;
lineIsCommentOnly = false;
lineIsLineCommentOnly = false;
lineEndsInCommentOnly = false;
doesLineStartComment = false;
currentLineBeginsWithBrace = false;
lineIsEmpty = false;
currentLineFirstBraceNum = string::npos;
tabIncrementIn = 0;
for (charNum = 0; isWhiteSpace(currentLine[charNum]) && charNum + 1 < (int) len; charNum++)
{
if (currentLine[charNum] == '\t' && !isInPreprocessor)
tabIncrementIn += tabSize - 1 - ((tabIncrementIn + charNum) % tabSize);
}
leadingSpaces = charNum + tabIncrementIn;
if (isSequenceReached("/*"))
{
doesLineStartComment = true;
if ((int) currentLine.length() > charNum + 2
&& currentLine.find("*/", charNum + 2) != string::npos)
lineIsCommentOnly = true;
}
else if (isSequenceReached("//"))
{
lineIsLineCommentOnly = true;
}
else if (isSequenceReached("{"))
{
currentLineBeginsWithBrace = true;
currentLineFirstBraceNum = charNum;
size_t firstText = currentLine.find_first_not_of(" \t", charNum + 1);
if (firstText != string::npos)
{
if (currentLine.compare(firstText, 2, "//") == 0)
lineIsLineCommentOnly = true;
else if (currentLine.compare(firstText, 2, "/*") == 0
|| isExecSQL(currentLine, firstText))
{
size_t j;
for (j = charNum + 1; j < firstText && isWhiteSpace(currentLine[j]); j++)
{
if (currentLine[j] == '\t')
tabIncrementIn += tabSize - 1 - ((tabIncrementIn + j) % tabSize);
}
leadingSpaces = j + tabIncrementIn;
if (currentLine.compare(firstText, 2, "/*") == 0)
doesLineStartComment = true;
}
}
}
else if (isWhiteSpace(currentLine[charNum]) && !(charNum + 1 < (int) currentLine.length()))
{
lineIsEmpty = true;
}
if (isInPreprocessor)
{
if (!doesLineStartComment)
leadingSpaces = 0;
charNum = 0;
}
}
void ASFormatter::appendChar(char ch, bool canBreakLine)
{
if (canBreakLine && isInLineBreak)
breakLine();
formattedLine.append(1, ch);
isImmediatelyPostCommentOnly = false;
if (maxCodeLength != string::npos)
{
if (isOkToSplitFormattedLine())
updateFormattedLineSplitPoints(ch);
if (formattedLine.length() > maxCodeLength)
testForTimeToSplitFormattedLine();
}
}
void ASFormatter::appendSequence(const string& sequence, bool canBreakLine)
{
if (canBreakLine && isInLineBreak)
breakLine();
formattedLine.append(sequence);
if (formattedLine.length() > maxCodeLength)
testForTimeToSplitFormattedLine();
}
void ASFormatter::appendOperator(const string& sequence, bool canBreakLine)
{
if (canBreakLine && isInLineBreak)
breakLine();
formattedLine.append(sequence);
if (maxCodeLength != string::npos)
{
if (isOkToSplitFormattedLine())
updateFormattedLineSplitPointsOperator(sequence);
if (formattedLine.length() > maxCodeLength)
testForTimeToSplitFormattedLine();
}
}
void ASFormatter::appendSpacePad()
{
int len = formattedLine.length();
if (len > 0 && !isWhiteSpace(formattedLine[len - 1]))
{
formattedLine.append(1, ' ');
spacePadNum++;
if (maxCodeLength != string::npos)
{
if (isOkToSplitFormattedLine())
updateFormattedLineSplitPoints(' ');
if (formattedLine.length() > maxCodeLength)
testForTimeToSplitFormattedLine();
}
}
}
void ASFormatter::appendSpaceAfter()
{
int len = currentLine.length();
if (charNum + 1 < len && !isWhiteSpace(currentLine[charNum + 1]))
{
formattedLine.append(1, ' ');
spacePadNum++;
if (maxCodeLength != string::npos)
{
if (isOkToSplitFormattedLine())
updateFormattedLineSplitPoints(' ');
if (formattedLine.length() > maxCodeLength)
testForTimeToSplitFormattedLine();
}
}
}
void ASFormatter::breakLine(bool isSplitLine )
{
isLineReady = true;
isInLineBreak = false;
spacePadNum = nextLineSpacePadNum;
nextLineSpacePadNum = 0;
readyFormattedLine = formattedLine;
formattedLine.erase();
prependEmptyLine = isPrependPostBlockEmptyLineRequested;
if (!isSplitLine)
{
formattedLineCommentNum = string::npos;
clearFormattedLineSplitPoints();
if (isAppendPostBlockEmptyLineRequested)
{
isAppendPostBlockEmptyLineRequested = false;
isPrependPostBlockEmptyLineRequested = true;
}
else
isPrependPostBlockEmptyLineRequested = false;
}
}
BraceType ASFormatter::getBraceType()
{
assert(currentChar == '{');
BraceType returnVal = NULL_TYPE;
if ((previousNonWSChar == '='
|| isBraceType(braceTypeStack->back(), ARRAY_TYPE))
&& previousCommandChar != ')'
&& !isNonParenHeader)
returnVal = ARRAY_TYPE;
else if (foundPreDefinitionHeader && previousCommandChar != ')')
{
returnVal = DEFINITION_TYPE;
if (foundNamespaceHeader)
returnVal = (BraceType)(returnVal | NAMESPACE_TYPE);
else if (foundClassHeader)
returnVal = (BraceType)(returnVal | CLASS_TYPE);
else if (foundStructHeader)
returnVal = (BraceType)(returnVal | STRUCT_TYPE);
else if (foundInterfaceHeader)
returnVal = (BraceType)(returnVal | INTERFACE_TYPE);
}
else if (isInEnum)
{
returnVal = (BraceType)(ARRAY_TYPE | ENUM_TYPE);
}
else
{
bool isCommandType = (foundPreCommandHeader
|| foundPreCommandMacro
|| (currentHeader != nullptr && isNonParenHeader)
|| (previousCommandChar == ')')
|| (previousCommandChar == ':' && !foundQuestionMark)
|| (previousCommandChar == ';')
|| ((previousCommandChar == '{' || previousCommandChar == '}')
&& isPreviousBraceBlockRelated)
|| (isInClassInitializer
&& (!isLegalNameChar(previousNonWSChar) || foundPreCommandHeader))
|| foundTrailingReturnType
|| isInObjCMethodDefinition
|| isInObjCInterface
|| isJavaStaticConstructor
|| isSharpDelegate);
if (!isCommandType && isSharpStyle() && isNextWordSharpNonParenHeader(charNum + 1))
{
isCommandType = true;
isSharpAccessor = true;
}
if (isInExternC)
returnVal = (isCommandType ? COMMAND_TYPE : EXTERN_TYPE);
else
returnVal = (isCommandType ? COMMAND_TYPE : ARRAY_TYPE);
}
int foundOneLineBlock = isOneLineBlockReached(currentLine, charNum);
if (foundOneLineBlock == 2 && returnVal == COMMAND_TYPE)
returnVal = ARRAY_TYPE;
if (foundOneLineBlock > 0)
{
returnVal = (BraceType) (returnVal | SINGLE_LINE_TYPE);
if (breakCurrentOneLineBlock)
returnVal = (BraceType) (returnVal | BREAK_BLOCK_TYPE);
if (foundOneLineBlock == 3)
returnVal = (BraceType)(returnVal | EMPTY_BLOCK_TYPE);
}
if (isBraceType(returnVal, ARRAY_TYPE))
{
if (isNonInStatementArrayBrace())
{
returnVal = (BraceType)(returnVal | ARRAY_NIS_TYPE);
isNonInStatementArray = true;
isImmediatelyPostNonInStmt = false; nonInStatementBrace = formattedLine.length() - 1;
}
if (isUniformInitializerBrace())
returnVal = (BraceType)(returnVal | INIT_TYPE);
}
return returnVal;
}
bool ASFormatter::isClassInitializer() const
{
assert(currentChar == ':');
assert(previousChar != ':' && peekNextChar() != ':');
bool foundClassInitializer = false;
if (foundQuestionMark)
{
}
else if (parenStack->back() > 0)
{
}
else if (isInEnum)
{
}
else if (isCStyle()
&& !isInCase
&& (previousCommandChar == ')' || foundPreCommandHeader))
{
foundClassInitializer = true;
}
return foundClassInitializer;
}
bool ASFormatter::isEmptyLine(const string& line) const
{
return line.find_first_not_of(" \t") == string::npos;
}
bool ASFormatter::isExternC() const
{
assert(!isWhiteSpace(currentLine[charNum]));
size_t startQuote = currentLine.find_first_of(" \t\"", charNum);
if (startQuote == string::npos)
return false;
startQuote = currentLine.find_first_not_of(" \t", startQuote);
if (startQuote == string::npos)
return false;
if (currentLine.compare(startQuote, 3, "\"C\"") != 0)
return false;
return true;
}
bool ASFormatter::isPointerOrReference() const
{
assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
if (isJavaStyle())
return false;
if (isCharImmediatelyPostOperator)
return false;
string lastWord = getPreviousWord(currentLine, charNum);
if (lastWord.empty())
lastWord = " ";
string nextText = peekNextText(currentLine.substr(charNum + 1));
if (nextText.length() == 0)
nextText = " ";
char nextChar = nextText[0];
if (isDigit(lastWord[0])
|| isDigit(nextChar)
|| nextChar == '!'
|| nextChar == '~')
return false;
if (currentChar == '*'
&& charNum < (int) currentLine.length() - 1
&& isWhiteSpace(currentLine[charNum + 1])
&& nextChar == '*')
return false;
if ((foundCastOperator && nextChar == '>')
|| isPointerOrReferenceVariable(lastWord))
return true;
if (isInClassInitializer
&& previousNonWSChar != '('
&& previousNonWSChar != '{'
&& previousCommandChar != ','
&& nextChar != ')'
&& nextChar != '}')
return false;
if (currentChar == '&' && nextChar == '&')
{
if (previousNonWSChar == '>')
return true;
string followingText;
if ((int) currentLine.length() > charNum + 2)
followingText = peekNextText(currentLine.substr(charNum + 2));
if (followingText.length() > 0 && followingText[0] == ')')
return true;
if (currentHeader != nullptr || isInPotentialCalculation)
return false;
if (parenStack->back() > 0 && isBraceType(braceTypeStack->back(), COMMAND_TYPE))
return false;
return true;
}
if (nextChar == '*'
|| previousNonWSChar == '='
|| previousNonWSChar == '('
|| previousNonWSChar == '['
|| isCharImmediatelyPostReturn
|| isInTemplate
|| isCharImmediatelyPostTemplate
|| currentHeader == &AS_CATCH
|| currentHeader == &AS_FOREACH
|| currentHeader == &AS_QFOREACH)
return true;
if (isBraceType(braceTypeStack->back(), ARRAY_TYPE)
&& isLegalNameChar(lastWord[0])
&& isLegalNameChar(nextChar)
&& previousNonWSChar != ')')
{
if (isArrayOperator())
return false;
}
if (parenStack->back() > 0
&& isLegalNameChar(lastWord[0])
&& isLegalNameChar(nextChar))
{
const string* followingOperator = getFollowingOperator();
if (followingOperator != nullptr
&& followingOperator != &AS_MULT
&& followingOperator != &AS_BIT_AND)
{
if (followingOperator == &AS_ASSIGN || followingOperator == &AS_COLON)
return true;
return false;
}
if (isBraceType(braceTypeStack->back(), COMMAND_TYPE)
|| squareBracketCount > 0)
return false;
return true;
}
if (parenStack->back() > 0
&& nextChar == '('
&& previousNonWSChar != ','
&& previousNonWSChar != '('
&& previousNonWSChar != '!'
&& previousNonWSChar != '&'
&& previousNonWSChar != '*'
&& previousNonWSChar != '|')
return false;
if (nextChar == '-'
|| nextChar == '+')
{
size_t nextNum = currentLine.find_first_not_of(" \t", charNum + 1);
if (nextNum != string::npos)
{
if (currentLine.compare(nextNum, 2, "++") != 0
&& currentLine.compare(nextNum, 2, "--") != 0)
return false;
}
}
bool isPR = (!isInPotentialCalculation
|| (!isLegalNameChar(previousNonWSChar)
&& !(previousNonWSChar == ')' && nextChar == '(')
&& !(previousNonWSChar == ')' && currentChar == '*' && !isImmediatelyPostCast())
&& previousNonWSChar != ']')
|| (!isWhiteSpace(nextChar)
&& nextChar != '-'
&& nextChar != '('
&& nextChar != '['
&& !isLegalNameChar(nextChar))
);
return isPR;
}
bool ASFormatter::isDereferenceOrAddressOf() const
{
assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
if (isCharImmediatelyPostTemplate)
return false;
if (previousNonWSChar == '='
|| previousNonWSChar == ','
|| previousNonWSChar == '.'
|| previousNonWSChar == '{'
|| previousNonWSChar == '>'
|| previousNonWSChar == '<'
|| previousNonWSChar == '?'
|| isCharImmediatelyPostLineComment
|| isCharImmediatelyPostComment
|| isCharImmediatelyPostReturn)
return true;
char nextChar = peekNextChar();
if (currentChar == '*' && nextChar == '*')
{
if (previousNonWSChar == '(')
return true;
if ((int) currentLine.length() < charNum + 2)
return true;
return false;
}
if (currentChar == '&' && nextChar == '&')
{
if (previousNonWSChar == '(' || isInTemplate)
return true;
if ((int) currentLine.length() < charNum + 2)
return true;
return false;
}
if (charNum == (int) currentLine.find_first_not_of(" \t")
&& (isBraceType(braceTypeStack->back(), COMMAND_TYPE)
|| parenStack->back() != 0))
return true;
string nextText = peekNextText(currentLine.substr(charNum + 1));
if (nextText.length() > 0)
{
if (nextText[0] == ')' || nextText[0] == '>'
|| nextText[0] == ',' || nextText[0] == '=')
return false;
if (nextText[0] == ';')
return true;
}
if ((currentChar == '*' && nextChar == '&')
|| (previousNonWSChar == '*' && currentChar == '&'))
return false;
if (!isBraceType(braceTypeStack->back(), COMMAND_TYPE)
&& parenStack->back() == 0)
return false;
string lastWord = getPreviousWord(currentLine, charNum);
if (lastWord == "else" || lastWord == "delete")
return true;
if (isPointerOrReferenceVariable(lastWord))
return false;
bool isDA = (!(isLegalNameChar(previousNonWSChar) || previousNonWSChar == '>')
|| (nextText.length() > 0 && !isLegalNameChar(nextText[0]) && nextText[0] != '/')
|| (ispunct((unsigned char)previousNonWSChar) && previousNonWSChar != '.')
|| isCharImmediatelyPostReturn);
return isDA;
}
bool ASFormatter::isPointerOrReferenceCentered() const
{
assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
int prNum = charNum;
int lineLength = (int) currentLine.length();
if (peekNextChar() == ' ')
return false;
if (prNum < 1
|| currentLine[prNum - 1] != ' ')
return false;
if (prNum < 2
|| currentLine[prNum - 2] == ' ')
return false;
if (prNum + 1 < lineLength
&& (currentLine[prNum + 1] == '*' || currentLine[prNum + 1] == '&'))
prNum++;
if (prNum + 1 <= lineLength
&& currentLine[prNum + 1] != ' ')
return false;
if (prNum + 2 < lineLength
&& currentLine[prNum + 2] == ' ')
return false;
return true;
}
bool ASFormatter::isPointerOrReferenceVariable(const string& word) const
{
return (word == "char"
|| word == "int"
|| word == "void"
|| (word.length() >= 6 && word.compare(word.length() - 2, 2, "_t") == 0)
|| word == "INT"
|| word == "VOID");
}
bool ASFormatter::isUnaryOperator() const
{
assert(currentChar == '+' || currentChar == '-');
return ((isCharImmediatelyPostReturn || !isLegalNameChar(previousCommandChar))
&& previousCommandChar != '.'
&& previousCommandChar != '\"'
&& previousCommandChar != '\''
&& previousCommandChar != ')'
&& previousCommandChar != ']');
}
bool ASFormatter::isInSwitchStatement() const
{
assert(isInLineComment || isInComment);
if (!preBraceHeaderStack->empty())
for (size_t i = 1; i < preBraceHeaderStack->size(); i++)
if (preBraceHeaderStack->at(i) == &AS_SWITCH)
return true;
return false;
}
bool ASFormatter::isInExponent() const
{
assert(currentChar == '+' || currentChar == '-');
if (charNum >= 2)
{
char prevPrevFormattedChar = currentLine[charNum - 2];
char prevFormattedChar = currentLine[charNum - 1];
return ((prevFormattedChar == 'e' || prevFormattedChar == 'E')
&& (prevPrevFormattedChar == '.' || isDigit(prevPrevFormattedChar)));
}
return false;
}
bool ASFormatter::isNonInStatementArrayBrace() const
{
bool returnVal = false;
char nextChar = peekNextChar();
if (currentLineBeginsWithBrace
&& charNum == (int) currentLineFirstBraceNum
&& nextChar != '}')
returnVal = true;
if (isWhiteSpace(nextChar)
|| isBeforeAnyLineEndComment(charNum)
|| nextChar == '{')
returnVal = true;
if (isJavaStyle() && previousNonWSChar == ']')
returnVal = false;
return returnVal;
}
int ASFormatter::isOneLineBlockReached(const string& line, int startChar) const
{
assert(line[startChar] == '{');
bool isInComment_ = false;
bool isInQuote_ = false;
bool hasText = false;
int braceCount = 0;
int lineLength = line.length();
char quoteChar_ = ' ';
char ch = ' ';
char prevCh = ' ';
for (int i = startChar; i < lineLength; ++i)
{
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)
{
isInComment_ = true;
++i;
continue;
}
if (ch == '{')
{
++braceCount;
continue;
}
if (ch == '}')
{
--braceCount;
if (braceCount == 0)
{
if (parenStack->back() == 0 && prevCh != '}')
{
size_t peekNum = line.find_first_not_of(" \t", i + 1);
if (peekNum != string::npos && line[peekNum] == ',')
return 2;
}
if (!hasText)
return 3; return 1;
}
}
if (ch == ';')
continue;
if (!isWhiteSpace(ch))
{
hasText = true;
prevCh = ch;
}
}
return 0;
}
bool ASFormatter::isNextWordSharpNonParenHeader(int startChar) const
{
string nextText = peekNextText(currentLine.substr(startChar));
if (nextText.length() == 0)
return false;
if (nextText[0] == '[')
return true;
if (!isCharPotentialHeader(nextText, 0))
return false;
if (findKeyword(nextText, 0, AS_GET) || findKeyword(nextText, 0, AS_SET)
|| findKeyword(nextText, 0, AS_ADD) || findKeyword(nextText, 0, AS_REMOVE))
return true;
return false;
}
bool ASFormatter::isNextCharOpeningBrace(int startChar) const
{
bool retVal = false;
string nextText = peekNextText(currentLine.substr(startChar));
if (nextText.length() > 0
&& nextText.compare(0, 1, "{") == 0)
retVal = true;
return retVal;
}
bool ASFormatter::isOperatorPaddingDisabled() const
{
size_t commentStart = currentLine.find("//", charNum);
if (commentStart == string::npos)
{
commentStart = currentLine.find("/*", charNum);
if (commentStart != string::npos)
{
size_t commentEnd = currentLine.find("*/", commentStart + 2);
if (commentEnd == string::npos)
commentStart = string::npos;
}
}
if (commentStart == string::npos)
return false;
size_t noPadStart = currentLine.find("*NOPAD*", commentStart);
if (noPadStart == string::npos)
return false;
return true;
}
bool ASFormatter::isUniformInitializerBrace() const
{
if (isCStyle() && !isInEnum && !isImmediatelyPostPreprocessor)
{
if (isInClassInitializer
|| isLegalNameChar(previousNonWSChar))
return true;
}
return false;
}
bool ASFormatter::isMultiStatementLine() const
{
assert((isImmediatelyPostHeader || foundClosingHeader));
bool isInComment_ = false;
bool isInQuote_ = false;
int semiCount_ = 0;
int parenCount_ = 0;
int braceCount_ = 0;
for (size_t i = 0; i < currentLine.length(); i++)
{
if (isInComment_)
{
if (currentLine.compare(i, 2, "*/") == 0)
{
isInComment_ = false;
continue;
}
}
if (currentLine.compare(i, 2, "/*") == 0)
{
isInComment_ = true;
continue;
}
if (currentLine.compare(i, 2, "//") == 0)
return false;
if (isInQuote_)
{
if (currentLine[i] == '"' || currentLine[i] == '\'')
isInQuote_ = false;
continue;
}
if (currentLine[i] == '"' || currentLine[i] == '\'')
{
isInQuote_ = true;
continue;
}
if (currentLine[i] == '(')
{
++parenCount_;
continue;
}
if (currentLine[i] == ')')
{
--parenCount_;
continue;
}
if (parenCount_ > 0)
continue;
if (currentLine[i] == '{')
{
++braceCount_;
}
if (currentLine[i] == '}')
{
--braceCount_;
}
if (braceCount_ > 0)
continue;
if (currentLine[i] == ';')
{
++semiCount_;
if (semiCount_ > 1)
return true;
continue;
}
}
return false;
}
string ASFormatter::peekNextText(const string& firstLine,
bool endOnEmptyLine ,
shared_ptr<ASPeekStream> streamArg ) const
{
bool isFirstLine = true;
string nextLine_ = firstLine;
size_t firstChar = string::npos;
shared_ptr<ASPeekStream> stream = streamArg;
if (stream == nullptr) stream = make_shared<ASPeekStream>(sourceIterator);
bool isInComment_ = false;
while (stream->hasMoreLines() || isFirstLine)
{
if (isFirstLine)
isFirstLine = false;
else
nextLine_ = stream->peekNextLine();
firstChar = nextLine_.find_first_not_of(" \t");
if (firstChar == string::npos)
{
if (endOnEmptyLine && !isInComment_)
break;
continue;
}
if (nextLine_.compare(firstChar, 2, "/*") == 0)
{
firstChar += 2;
isInComment_ = true;
}
if (isInComment_)
{
firstChar = nextLine_.find("*/", firstChar);
if (firstChar == string::npos)
continue;
firstChar += 2;
isInComment_ = false;
firstChar = nextLine_.find_first_not_of(" \t", firstChar);
if (firstChar == string::npos)
continue;
}
if (nextLine_.compare(firstChar, 2, "//") == 0)
continue;
break;
}
if (firstChar == string::npos)
nextLine_ = "";
else
nextLine_ = nextLine_.substr(firstChar);
return nextLine_;
}
void ASFormatter::adjustComments()
{
assert(spacePadNum != 0);
assert(isSequenceReached("//") || isSequenceReached("/*"));
if (isSequenceReached("/*"))
{
size_t endNum = currentLine.find("*/", charNum + 2);
if (endNum == string::npos)
return;
if (currentLine.find_first_not_of(" \t", endNum + 2) != string::npos)
return;
}
size_t len = formattedLine.length();
if (formattedLine[len - 1] == '\t')
return;
if (spacePadNum < 0)
{
int adjust = -spacePadNum; formattedLine.append(adjust, ' ');
}
else if (spacePadNum > 0)
{
int adjust = spacePadNum;
size_t lastText = formattedLine.find_last_not_of(' ');
if (lastText != string::npos
&& lastText < len - adjust - 1)
formattedLine.resize(len - adjust);
else if (len > lastText + 2)
formattedLine.resize(lastText + 2);
else if (len < lastText + 2)
formattedLine.append(len - lastText, ' ');
}
}
void ASFormatter::appendCharInsideComments()
{
if (formattedLineCommentNum == string::npos || formattedLineCommentNum == 0)
{
appendCurrentChar(); return;
}
assert(formattedLine.compare(formattedLineCommentNum, 2, "//") == 0
|| formattedLine.compare(formattedLineCommentNum, 2, "/*") == 0);
size_t end = formattedLineCommentNum;
size_t beg = formattedLine.find_last_not_of(" \t", end - 1);
if (beg == string::npos)
{
appendCurrentChar(); return;
}
beg++;
if (end - beg < 3) formattedLine.insert(beg, 3 - end + beg, ' ');
if (formattedLine[beg] == '\t') formattedLine.insert(beg, 1, ' ');
formattedLine[beg + 1] = currentChar;
testForTimeToSplitFormattedLine();
if (isBeforeComment())
breakLine();
else if (isCharImmediatelyPostLineComment)
shouldBreakLineAtNextChar = true;
}
void ASFormatter::padOperators(const string* newOperator)
{
assert(shouldPadOperators);
assert(newOperator != nullptr);
char nextNonWSChar = ASBase::peekNextChar(currentLine, charNum);
bool shouldPad = (newOperator != &AS_SCOPE_RESOLUTION
&& newOperator != &AS_PLUS_PLUS
&& newOperator != &AS_MINUS_MINUS
&& newOperator != &AS_NOT
&& newOperator != &AS_BIT_NOT
&& newOperator != &AS_ARROW
&& !(newOperator == &AS_COLON && !foundQuestionMark && (isInObjCMethodDefinition || isInObjCInterface
|| isInObjCSelector || squareBracketCount != 0))
&& !(newOperator == &AS_MINUS && isInExponent())
&& !(newOperator == &AS_PLUS && isInExponent())
&& !((newOperator == &AS_PLUS || newOperator == &AS_MINUS) && (previousNonWSChar == '('
|| previousNonWSChar == '['
|| previousNonWSChar == '='
|| previousNonWSChar == ','
|| previousNonWSChar == ':'
|| previousNonWSChar == '{'))
&& !(newOperator == &AS_MULT
&& (previousNonWSChar == '.'
|| previousNonWSChar == '>')) && !(newOperator == &AS_MULT && peekNextChar() == '>')
&& !((isInTemplate || isImmediatelyPostTemplate)
&& (newOperator == &AS_LS || newOperator == &AS_GR))
&& !(newOperator == &AS_GCC_MIN_ASSIGN
&& ASBase::peekNextChar(currentLine, charNum + 1) == '>')
&& !(newOperator == &AS_GR && previousNonWSChar == '?')
&& !(newOperator == &AS_QUESTION && isJavaStyle()
&& (previousNonWSChar == '<'
|| nextNonWSChar == '>'
|| nextNonWSChar == '.'))
&& !(newOperator == &AS_QUESTION && isSharpStyle()
&& (nextNonWSChar == '.'
|| nextNonWSChar == '['))
&& !isCharImmediatelyPostOperator
&& !isInCase
&& !isInAsm
&& !isInAsmOneLine
&& !isInAsmBlock
);
if (shouldPad
&& !(newOperator == &AS_COLON
&& (!foundQuestionMark && !isInEnum) && currentHeader != &AS_FOR)
&& !(newOperator == &AS_QUESTION && isSharpStyle() && currentLine.find(':', charNum + 1) == string::npos)
)
appendSpacePad();
appendOperator(*newOperator);
goForward(newOperator->length() - 1);
currentChar = (*newOperator)[newOperator->length() - 1];
if (shouldPad
&& !isBeforeAnyComment()
&& !(newOperator == &AS_PLUS && isUnaryOperator())
&& !(newOperator == &AS_MINUS && isUnaryOperator())
&& !(currentLine.compare(charNum + 1, 1, AS_SEMICOLON) == 0)
&& !(currentLine.compare(charNum + 1, 2, AS_SCOPE_RESOLUTION) == 0)
&& !(peekNextChar() == ',')
&& !(newOperator == &AS_QUESTION && isSharpStyle() && peekNextChar() == '[')
)
appendSpaceAfter();
}
void ASFormatter::formatPointerOrReference()
{
assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
assert(!isJavaStyle());
int pa = pointerAlignment;
int ra = referenceAlignment;
int itemAlignment = (currentChar == '*' || currentChar == '^') ? pa : ((ra == REF_SAME_AS_PTR) ? pa : ra);
int ptrLength = 1;
char peekedChar = peekNextChar();
if ((currentChar == '*' && peekedChar == '*')
|| (currentChar == '&' && peekedChar == '&'))
{
ptrLength = 2;
size_t nextChar = currentLine.find_first_not_of(" \t", charNum + 2);
if (nextChar == string::npos)
peekedChar = ' ';
else
peekedChar = currentLine[nextChar];
}
if (peekedChar == ')' || peekedChar == '>' || peekedChar == ',')
{
formatPointerOrReferenceCast();
return;
}
if (charNum > 0
&& !isWhiteSpace(currentLine[charNum - 1])
&& formattedLine.length() > 0
&& isWhiteSpace(formattedLine[formattedLine.length() - 1]))
{
formattedLine.erase(formattedLine.length() - 1);
spacePadNum--;
}
if (itemAlignment == PTR_ALIGN_TYPE)
{
formatPointerOrReferenceToType();
}
else if (itemAlignment == PTR_ALIGN_MIDDLE)
{
formatPointerOrReferenceToMiddle();
}
else if (itemAlignment == PTR_ALIGN_NAME)
{
formatPointerOrReferenceToName();
}
else {
formattedLine.append(ptrLength, currentChar);
if (ptrLength > 1)
goForward(ptrLength - 1);
}
}
void ASFormatter::formatPointerOrReferenceToType()
{
assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
assert(!isJavaStyle());
bool isOldPRCentered = isPointerOrReferenceCentered();
size_t prevCh = formattedLine.find_last_not_of(" \t");
if (prevCh == string::npos)
prevCh = 0;
if (formattedLine.length() == 0 || prevCh == formattedLine.length() - 1)
formattedLine.append(1, currentChar);
else
{
string charSave = formattedLine.substr(prevCh + 1, 1);
formattedLine[prevCh + 1] = currentChar;
formattedLine.append(charSave);
}
if (isSequenceReached("**") || isSequenceReached("&&"))
{
if (formattedLine.length() == 1)
formattedLine.append(1, currentChar);
else
formattedLine.insert(prevCh + 2, 1, currentChar);
goForward(1);
}
if (charNum < (int) currentLine.length() - 1
&& !isWhiteSpace(currentLine[charNum + 1])
&& currentLine[charNum + 1] != ')')
appendSpacePad();
if (isOldPRCentered
&& isWhiteSpace(formattedLine[formattedLine.length() - 1]))
{
formattedLine.erase(formattedLine.length() - 1, 1);
spacePadNum--;
}
if (maxCodeLength != string::npos)
{
size_t index = formattedLine.length() - 1;
if (isWhiteSpace(formattedLine[index]))
{
updateFormattedLineSplitPointsPointerOrReference(index);
testForTimeToSplitFormattedLine();
}
}
}
void ASFormatter::formatPointerOrReferenceToMiddle()
{
assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
assert(!isJavaStyle());
size_t wsBefore = currentLine.find_last_not_of(" \t", charNum - 1);
if (wsBefore == string::npos)
wsBefore = 0;
else
wsBefore = charNum - wsBefore - 1;
string sequenceToInsert(1, currentChar);
if (isSequenceReached("**"))
{
sequenceToInsert = "**";
goForward(1);
}
else if (isSequenceReached("&&"))
{
sequenceToInsert = "&&";
goForward(1);
}
else if (currentChar == '*' && peekNextChar() == '&'
&& (referenceAlignment == REF_ALIGN_TYPE
|| referenceAlignment == REF_ALIGN_MIDDLE
|| referenceAlignment == REF_SAME_AS_PTR))
{
sequenceToInsert = "*&";
goForward(1);
for (size_t i = charNum; i < currentLine.length() - 1 && isWhiteSpace(currentLine[i]); i++)
goForward(1);
}
if (isBeforeAnyComment())
{
appendSpacePad();
formattedLine.append(sequenceToInsert);
appendSpaceAfter();
return;
}
bool isAfterScopeResolution = previousNonWSChar == ':';
size_t charNumSave = charNum;
if (currentLine.find_first_not_of(" \t", charNum + 1) == string::npos)
{
if (wsBefore == 0 && !isAfterScopeResolution)
formattedLine.append(1, ' ');
formattedLine.append(sequenceToInsert);
return;
}
for (size_t i = charNum + 1; i < currentLine.length() && isWhiteSpace(currentLine[i]); i++)
{
goForward(1);
if (formattedLine.length() > 0)
formattedLine.append(1, currentLine[i]);
else
spacePadNum--;
}
size_t wsAfter = currentLine.find_first_not_of(" \t", charNumSave + 1);
if (wsAfter == string::npos || isBeforeAnyComment())
wsAfter = 0;
else
wsAfter = wsAfter - charNumSave - 1;
if (isAfterScopeResolution)
{
size_t lastText = formattedLine.find_last_not_of(" \t");
formattedLine.insert(lastText + 1, sequenceToInsert);
appendSpacePad();
}
else if (formattedLine.length() > 0)
{
if (wsBefore + wsAfter < 2)
{
size_t charsToAppend = (2 - (wsBefore + wsAfter));
formattedLine.append(charsToAppend, ' ');
spacePadNum += charsToAppend;
if (wsBefore == 0)
wsBefore++;
if (wsAfter == 0)
wsAfter++;
}
size_t padAfter = (wsBefore + wsAfter) / 2;
size_t index = formattedLine.length() - padAfter;
formattedLine.insert(index, sequenceToInsert);
}
else {
formattedLine.append(sequenceToInsert);
if (wsAfter == 0)
wsAfter++;
formattedLine.append(wsAfter, ' ');
spacePadNum += wsAfter;
}
if (maxCodeLength != string::npos && formattedLine.length() > 0)
{
size_t index = formattedLine.find_last_not_of(" \t");
if (index != string::npos && (index < formattedLine.length() - 1))
{
index++;
updateFormattedLineSplitPointsPointerOrReference(index);
testForTimeToSplitFormattedLine();
}
}
}
void ASFormatter::formatPointerOrReferenceToName()
{
assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
assert(!isJavaStyle());
bool isOldPRCentered = isPointerOrReferenceCentered();
size_t startNum = formattedLine.find_last_not_of(" \t");
if (startNum == string::npos)
startNum = 0;
string sequenceToInsert(1, currentChar);
if (isSequenceReached("**"))
{
sequenceToInsert = "**";
goForward(1);
}
else if (isSequenceReached("&&"))
{
sequenceToInsert = "&&";
goForward(1);
}
else if (currentChar == '*' && peekNextChar() == '&')
{
sequenceToInsert = "*&";
goForward(1);
for (size_t i = charNum; i < currentLine.length() - 1 && isWhiteSpace(currentLine[i]); i++)
goForward(1);
}
char peekedChar = peekNextChar();
bool isAfterScopeResolution = previousNonWSChar == ':'; if (!isBeforeAnyComment()
&& (int) currentLine.find_first_not_of(" \t", charNum + 1) > charNum)
{
for (size_t i = charNum + 1; i < currentLine.length() && isWhiteSpace(currentLine[i]); i++)
{
if (shouldPadParensOutside && peekedChar == '(' && !isOldPRCentered)
{
size_t start = currentLine.find_first_not_of("( \t", charNum + 1);
if (start != string::npos && currentLine[start] != ')')
break;
}
goForward(1);
if (formattedLine.length() > 0)
formattedLine.append(1, currentLine[i]);
else
spacePadNum--;
}
}
if (isAfterScopeResolution)
{
size_t lastText = formattedLine.find_last_not_of(" \t");
if (lastText != string::npos && lastText + 1 < formattedLine.length())
formattedLine.erase(lastText + 1);
}
else if (formattedLine.length() > 0
&& (formattedLine.length() <= startNum + 1
|| !isWhiteSpace(formattedLine[startNum + 1])))
{
formattedLine.insert(startNum + 1, 1, ' ');
spacePadNum++;
}
appendSequence(sequenceToInsert, false);
if (isOldPRCentered
&& formattedLine.length() > startNum + 1
&& isWhiteSpace(formattedLine[startNum + 1])
&& !isBeforeAnyComment())
{
formattedLine.erase(startNum + 1, 1);
spacePadNum--;
}
if (peekedChar == '=')
{
appendSpaceAfter();
if (formattedLine.length() > startNum
&& isWhiteSpace(formattedLine[startNum + 1])
&& isWhiteSpace(formattedLine[startNum + 2]))
{
formattedLine.erase(startNum + 1, 1);
spacePadNum--;
}
}
if (maxCodeLength != string::npos)
{
size_t index = formattedLine.find_last_of(" \t");
if (index != string::npos
&& index < formattedLine.length() - 1
&& (formattedLine[index + 1] == '*'
|| formattedLine[index + 1] == '&'
|| formattedLine[index + 1] == '^'))
{
updateFormattedLineSplitPointsPointerOrReference(index);
testForTimeToSplitFormattedLine();
}
}
}
void ASFormatter::formatPointerOrReferenceCast()
{
assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
assert(!isJavaStyle());
int pa = pointerAlignment;
int ra = referenceAlignment;
int itemAlignment = (currentChar == '*' || currentChar == '^') ? pa : ((ra == REF_SAME_AS_PTR) ? pa : ra);
string sequenceToInsert(1, currentChar);
if (isSequenceReached("**") || isSequenceReached("&&"))
{
goForward(1);
sequenceToInsert.append(1, currentLine[charNum]);
}
if (itemAlignment == PTR_ALIGN_NONE)
{
appendSequence(sequenceToInsert, false);
return;
}
char prevCh = ' ';
size_t prevNum = formattedLine.find_last_not_of(" \t");
if (prevNum != string::npos)
{
prevCh = formattedLine[prevNum];
if (prevNum + 1 < formattedLine.length()
&& isWhiteSpace(formattedLine[prevNum + 1])
&& prevCh != '(')
{
spacePadNum -= (formattedLine.length() - 1 - prevNum);
formattedLine.erase(prevNum + 1);
}
}
bool isAfterScopeResolution = previousNonWSChar == ':';
if ((itemAlignment == PTR_ALIGN_MIDDLE || itemAlignment == PTR_ALIGN_NAME)
&& !isAfterScopeResolution && prevCh != '(')
{
appendSpacePad();
if (maxCodeLength != string::npos && formattedLine.length() > 0)
updateFormattedLineSplitPointsPointerOrReference(formattedLine.length() - 1);
appendSequence(sequenceToInsert, false);
}
else
appendSequence(sequenceToInsert, false);
}
void ASFormatter::padParens()
{
assert(currentChar == '(' || currentChar == ')');
assert(shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens || shouldPadFirstParen);
int spacesOutsideToDelete = 0;
int spacesInsideToDelete = 0;
if (currentChar == '(')
{
spacesOutsideToDelete = formattedLine.length() - 1;
spacesInsideToDelete = 0;
if (shouldUnPadParens)
{
char lastChar = ' ';
bool prevIsParenHeader = false;
size_t i = formattedLine.find_last_not_of(" \t");
if (i != string::npos)
{
if (formattedLine[i] == '{')
spacesOutsideToDelete = 0;
else if (isCharImmediatelyPostPointerOrReference)
spacesOutsideToDelete = 0;
else
{
spacesOutsideToDelete -= i;
lastChar = formattedLine[i];
string prevWord = getPreviousWord(formattedLine, formattedLine.length());
const string* prevWordH = nullptr;
if (shouldPadHeader
&& prevWord.length() > 0
&& isCharPotentialHeader(prevWord, 0))
prevWordH = ASBase::findHeader(prevWord, 0, headers);
if (prevWordH != nullptr)
prevIsParenHeader = true;
else if (prevWord == AS_RETURN) prevIsParenHeader = true;
else if ((prevWord == AS_NEW || prevWord == AS_DELETE)
&& shouldPadHeader) prevIsParenHeader = true;
else if (isCStyle() && prevWord == AS_THROW && shouldPadHeader) prevIsParenHeader = true;
else if (prevWord == "and" || prevWord == "or" || prevWord == "in") prevIsParenHeader = true;
else if (prevWord == "bool"
|| prevWord == "int"
|| prevWord == "void"
|| prevWord == "void*"
|| prevWord == "char"
|| prevWord == "char*"
|| prevWord == "long"
|| prevWord == "double"
|| prevWord == "float"
|| (prevWord.length() >= 4 && prevWord.compare(prevWord.length() - 2, 2, "_t") == 0)
|| prevWord == "Int32"
|| prevWord == "UInt32"
|| prevWord == "Int64"
|| prevWord == "UInt64"
|| prevWord == "BOOL"
|| prevWord == "DWORD"
|| prevWord == "HWND"
|| prevWord == "INT"
|| prevWord == "LPSTR"
|| prevWord == "VOID"
|| prevWord == "LPVOID"
)
{
prevIsParenHeader = true;
}
}
}
if (shouldPadParensOutside || prevIsParenHeader)
spacesOutsideToDelete--;
else if (lastChar == '|' || lastChar == '&' || lastChar == ','
|| (lastChar == '(' && shouldPadParensInside)
|| (lastChar == '>' && !foundCastOperator)
|| lastChar == '<'
|| lastChar == '?'
|| lastChar == ':'
|| lastChar == ';'
|| lastChar == '='
|| lastChar == '+'
|| lastChar == '-'
|| lastChar == '*'
|| lastChar == '/'
|| lastChar == '%'
|| lastChar == '^'
)
spacesOutsideToDelete--;
if (spacesOutsideToDelete > 0)
{
formattedLine.erase(i + 1, spacesOutsideToDelete);
spacePadNum -= spacesOutsideToDelete;
}
}
char peekedCharOutside = peekNextChar();
if (shouldPadFirstParen && previousChar != '(' && peekedCharOutside != ')')
appendSpacePad();
else if (shouldPadParensOutside)
{
if (!(currentChar == '(' && peekedCharOutside == ')'))
appendSpacePad();
}
appendCurrentChar();
if (shouldUnPadParens)
{
size_t j = currentLine.find_first_not_of(" \t", charNum + 1);
if (j != string::npos)
spacesInsideToDelete = j - charNum - 1;
if (shouldPadParensInside)
spacesInsideToDelete--;
if (spacesInsideToDelete > 0)
{
currentLine.erase(charNum + 1, spacesInsideToDelete);
spacePadNum -= spacesInsideToDelete;
}
if (shouldConvertTabs
&& (int) currentLine.length() > charNum + 1
&& currentLine[charNum + 1] == '\t')
currentLine[charNum + 1] = ' ';
}
char peekedCharInside = peekNextChar();
if (shouldPadParensInside)
if (!(currentChar == '(' && peekedCharInside == ')'))
appendSpaceAfter();
}
else if (currentChar == ')')
{
if (shouldUnPadParens)
{
spacesInsideToDelete = formattedLine.length();
size_t i = formattedLine.find_last_not_of(" \t");
if (i != string::npos)
spacesInsideToDelete = formattedLine.length() - 1 - i;
if (shouldPadParensInside)
spacesInsideToDelete--;
if (spacesInsideToDelete > 0)
{
formattedLine.erase(i + 1, spacesInsideToDelete);
spacePadNum -= spacesInsideToDelete;
}
}
if (shouldPadParensInside)
if (!(previousChar == '(' && currentChar == ')'))
appendSpacePad();
appendCurrentChar();
if (shouldUnPadParens)
{
}
char peekedCharOutside = peekNextChar();
if (shouldPadParensOutside)
if (peekedCharOutside != ';'
&& peekedCharOutside != ','
&& peekedCharOutside != '.'
&& peekedCharOutside != '+' && peekedCharOutside != '-' && peekedCharOutside != ']')
appendSpaceAfter();
}
}
void ASFormatter::padObjCMethodPrefix()
{
assert(currentChar == '(' && isImmediatelyPostObjCMethodPrefix);
assert(shouldPadMethodPrefix || shouldUnPadMethodPrefix);
size_t prefix = formattedLine.find_first_of("+-");
if (prefix == string::npos)
return;
size_t paren = formattedLine.find_first_of('(');
if (paren == string::npos)
return;
int spaces = paren - prefix - 1;
if (shouldPadMethodPrefix)
{
if (spaces == 0)
{
formattedLine.insert(prefix + 1, 1, ' ');
spacePadNum += 1;
}
else if (spaces > 1)
{
formattedLine.erase(prefix + 1, spaces - 1);
spacePadNum -= spaces - 1;
}
}
else if (shouldUnPadMethodPrefix)
{
if (spaces > 0)
{
formattedLine.erase(prefix + 1, spaces);
spacePadNum -= spaces;
}
}
}
void ASFormatter::padObjCReturnType()
{
assert(currentChar == ')' && isInObjCReturnType);
assert(shouldPadReturnType || shouldUnPadReturnType);
size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
if (nextText == string::npos)
return;
int spaces = nextText - charNum - 1;
if (shouldPadReturnType)
{
if (spaces == 0)
{
if (formattedLine[formattedLine.length() - 1] != ' ')
{
formattedLine.append(" ");
spacePadNum += 1;
}
}
else if (spaces > 1)
{
currentLine.erase(charNum + 1, spaces - 1);
spacePadNum -= spaces - 1;
}
}
else if (shouldUnPadReturnType)
{
if (formattedLine[formattedLine.length() - 1] == ' ')
{
spacePadNum -= formattedLine.length() - 1 - nextText;
int lastText = formattedLine.find_last_not_of(" \t");
formattedLine.resize(lastText + 1);
}
if (spaces > 0)
{
currentLine.erase(charNum + 1, spaces);
spacePadNum -= spaces;
}
}
}
void ASFormatter::padObjCParamType()
{
assert((currentChar == '(' || currentChar == ')') && isInObjCMethodDefinition);
assert(!isImmediatelyPostObjCMethodPrefix && !isInObjCReturnType);
assert(shouldPadParamType || shouldUnPadParamType);
if (currentChar == '(')
{
size_t paramOpen = formattedLine.rfind('(');
assert(paramOpen != string::npos);
size_t prevText = formattedLine.find_last_not_of(" \t", paramOpen - 1);
if (prevText == string::npos)
return;
int spaces = paramOpen - prevText - 1;
if (shouldPadParamType
|| objCColonPadMode == COLON_PAD_ALL
|| objCColonPadMode == COLON_PAD_AFTER)
{
if (spaces == 0)
{
formattedLine.insert(paramOpen, 1, ' ');
spacePadNum += 1;
}
if (spaces > 1)
{
formattedLine.erase(prevText + 1, spaces - 1);
spacePadNum -= spaces - 1;
}
}
else if (shouldUnPadParamType
|| objCColonPadMode == COLON_PAD_NONE
|| objCColonPadMode == COLON_PAD_BEFORE)
{
if (spaces > 0)
{
formattedLine.erase(prevText + 1, spaces);
spacePadNum -= spaces;
}
}
}
else if (currentChar == ')')
{
size_t nextText = currentLine.find_first_not_of(" \t", charNum + 1);
if (nextText == string::npos)
return;
int spaces = nextText - charNum - 1;
if (shouldPadParamType)
{
if (spaces == 0)
{
if (formattedLine[formattedLine.length() - 1] != ' ')
{
formattedLine.append(" ");
spacePadNum += 1;
}
}
else if (spaces > 1)
{
currentLine.erase(charNum + 1, spaces - 1);
spacePadNum -= spaces - 1;
}
}
else if (shouldUnPadParamType)
{
if (formattedLine[formattedLine.length() - 1] == ' ')
{
spacePadNum -= 1;
int lastText = formattedLine.find_last_not_of(" \t");
formattedLine.resize(lastText + 1);
}
if (spaces > 0)
{
currentLine.erase(charNum + 1, spaces);
spacePadNum -= spaces;
}
}
}
}
void ASFormatter::formatOpeningBrace(BraceType braceType)
{
assert(!isBraceType(braceType, ARRAY_TYPE));
assert(currentChar == '{');
parenStack->emplace_back(0);
bool breakBrace = isCurrentBraceBroken();
if (breakBrace)
{
if (isBeforeAnyComment() && isOkToBreakBlock(braceType))
{
if (isBeforeAnyLineEndComment(charNum) && !currentLineBeginsWithBrace)
{
currentChar = ' '; if (parenStack->size() > 1)
parenStack->pop_back();
currentLine[charNum] = currentChar;
appendOpeningBrace = true; }
else if (!isBeforeMultipleLineEndComments(charNum))
breakLine();
}
else if (!isBraceType(braceType, SINGLE_LINE_TYPE))
{
formattedLine = rtrim(formattedLine);
breakLine();
}
else if ((shouldBreakOneLineBlocks || isBraceType(braceType, BREAK_BLOCK_TYPE))
&& !isBraceType(braceType, EMPTY_BLOCK_TYPE))
breakLine();
else if (!isInLineBreak)
appendSpacePad();
appendCurrentChar();
if (isBeforeComment()
&& formattedLine.length() > 0
&& formattedLine[0] == '{'
&& isOkToBreakBlock(braceType)
&& (braceFormatMode == BREAK_MODE
|| braceFormatMode == LINUX_MODE))
{
shouldBreakLineAtNextChar = true;
}
}
else {
if (isCharImmediatelyPostComment || isCharImmediatelyPostLineComment)
{
if (isOkToBreakBlock(braceType)
&& !(isCharImmediatelyPostComment && isCharImmediatelyPostLineComment) && !isImmediatelyPostPreprocessor
&& previousCommandChar != '{' && previousCommandChar != '}' && previousCommandChar != ';') {
appendCharInsideComments();
}
else
{
appendCurrentChar(); }
}
else if (previousCommandChar == '{'
|| (previousCommandChar == '}' && !isInClassInitializer)
|| previousCommandChar == ';') {
appendCurrentChar(); }
else
{
if (isEmptyLine(formattedLine))
appendCurrentChar(); else if (isOkToBreakBlock(braceType)
&& !(isImmediatelyPostPreprocessor
&& currentLineBeginsWithBrace))
{
if (!isBraceType(braceType, EMPTY_BLOCK_TYPE))
{
appendSpacePad();
appendCurrentChar(false); testForTimeToSplitFormattedLine(); if (isBeforeComment()
&& !isBeforeMultipleLineEndComments(charNum)
&& (!isBeforeAnyLineEndComment(charNum) || currentLineBeginsWithBrace))
{
shouldBreakLineAtNextChar = true;
currentLine.insert(charNum + 1, charNum + 1, ' ');
}
else if (!isBeforeAnyComment()) {
shouldBreakLineAtNextChar = true;
}
}
else
{
if (currentLineBeginsWithBrace && charNum == (int) currentLineFirstBraceNum)
{
appendSpacePad();
appendCurrentChar(false); shouldBreakLineAtNextChar = true;
}
else
{
appendSpacePad();
appendCurrentChar(); }
}
}
else
{
if (!isInLineBreak)
appendSpacePad();
appendCurrentChar(); }
}
}
}
void ASFormatter::formatClosingBrace(BraceType braceType)
{
assert(!isBraceType(braceType, ARRAY_TYPE));
assert(currentChar == '}');
if (parenStack->size() > 1)
parenStack->pop_back();
if (previousCommandChar == '{')
isImmediatelyPostEmptyBlock = true;
if (attachClosingBraceMode)
{
if ((isEmptyLine(formattedLine) || isCharImmediatelyPostLineComment
|| isCharImmediatelyPostComment
|| (isImmediatelyPostPreprocessor && (int) currentLine.find_first_not_of(" \t") == charNum)
)
&& (!isBraceType(braceType, SINGLE_LINE_TYPE) || isOkToBreakBlock(braceType)))
{
breakLine();
appendCurrentChar(); }
else
{
if (previousNonWSChar != '{'
&& (!isBraceType(braceType, SINGLE_LINE_TYPE)
|| isOkToBreakBlock(braceType)))
appendSpacePad();
appendCurrentChar(false); }
}
else if (!isBraceType(braceType, EMPTY_BLOCK_TYPE)
&& (isBraceType(braceType, BREAK_BLOCK_TYPE)
|| isOkToBreakBlock(braceType)))
{
breakLine();
appendCurrentChar();
}
else
{
appendCurrentChar();
}
if (isLegalNameChar(peekNextChar()))
appendSpaceAfter();
if (shouldBreakBlocks
&& currentHeader != nullptr
&& !isHeaderInMultiStatementLine
&& parenStack->back() == 0)
{
if (currentHeader == &AS_CASE || currentHeader == &AS_DEFAULT)
{
string nextText = peekNextText(currentLine.substr(charNum + 1));
if (nextText.length() > 0
&& nextText.substr(0, 5) != "break")
isAppendPostBlockEmptyLineRequested = true;
}
else
isAppendPostBlockEmptyLineRequested = true;
}
}
void ASFormatter::formatArrayBraces(BraceType braceType, bool isOpeningArrayBrace)
{
assert(isBraceType(braceType, ARRAY_TYPE));
assert(currentChar == '{' || currentChar == '}');
if (currentChar == '{')
{
if (isOpeningArrayBrace)
{
if (braceFormatMode == ATTACH_MODE
|| braceFormatMode == LINUX_MODE)
{
if (isBraceType(braceType, ENUM_TYPE)
&& formattingStyle == STYLE_MOZILLA)
{
isInLineBreak = true;
appendCurrentChar(); }
else if ((isImmediatelyPostPreprocessor
|| (formattedLine.length() > 0
&& formattedLine[formattedLine.length() - 1] == '\\'))
&& currentLineBeginsWithBrace)
{
isInLineBreak = true;
appendCurrentChar(); }
else if (isCharImmediatelyPostComment)
{
appendCurrentChar(); }
else if (isCharImmediatelyPostLineComment && !isBraceType(braceType, SINGLE_LINE_TYPE))
{
appendCharInsideComments();
}
else
{
if (isEmptyLine(formattedLine))
appendCurrentChar(); else
{
if (currentLineBeginsWithBrace
&& !isBraceType(braceType, SINGLE_LINE_TYPE))
{
appendSpacePad();
appendCurrentChar(false); testForTimeToSplitFormattedLine();
if (currentLineBeginsWithBrace
&& (int) currentLineFirstBraceNum == charNum)
shouldBreakLineAtNextChar = true;
}
else
{
if (previousNonWSChar != '(')
{
if (!isBraceType(braceType, INIT_TYPE))
appendSpacePad();
}
appendCurrentChar();
}
}
}
}
else if (braceFormatMode == BREAK_MODE)
{
if (isWhiteSpace(peekNextChar()) && !isInVirginLine)
breakLine();
else if (isBeforeAnyComment())
{
if (isBeforeAnyLineEndComment(charNum) && !currentLineBeginsWithBrace)
{
currentChar = ' '; appendOpeningBrace = true; }
}
if (!isInLineBreak && previousNonWSChar != '(')
{
if (!isBraceType(braceType, INIT_TYPE))
appendSpacePad();
}
appendCurrentChar();
if (currentLineBeginsWithBrace
&& (int) currentLineFirstBraceNum == charNum
&& !isBraceType(braceType, SINGLE_LINE_TYPE))
shouldBreakLineAtNextChar = true;
}
else if (braceFormatMode == RUN_IN_MODE)
{
if (isWhiteSpace(peekNextChar()) && !isInVirginLine)
breakLine();
else if (isBeforeAnyComment())
{
if (isBeforeAnyLineEndComment(charNum) && !currentLineBeginsWithBrace)
{
currentChar = ' '; appendOpeningBrace = true; }
}
if (!isInLineBreak && previousNonWSChar != '(')
{
if (!isBraceType(braceType, INIT_TYPE))
appendSpacePad();
}
appendCurrentChar();
}
else if (braceFormatMode == NONE_MODE)
{
if (currentLineBeginsWithBrace
&& charNum == (int) currentLineFirstBraceNum)
{
appendCurrentChar(); }
else
{
if (previousNonWSChar != '(')
{
if (!isBraceType(braceType, INIT_TYPE))
appendSpacePad();
}
appendCurrentChar(false); }
}
}
else {
if (braceFormatMode == RUN_IN_MODE)
{
if (previousNonWSChar == '{'
&& braceTypeStack->size() > 2
&& !isBraceType((*braceTypeStack)[braceTypeStack->size() - 2],
SINGLE_LINE_TYPE))
formatArrayRunIn();
}
else if (!isInLineBreak
&& !isWhiteSpace(peekNextChar())
&& previousNonWSChar == '{'
&& braceTypeStack->size() > 2
&& !isBraceType((*braceTypeStack)[braceTypeStack->size() - 2],
SINGLE_LINE_TYPE))
formatArrayRunIn();
appendCurrentChar();
}
}
else if (currentChar == '}')
{
if (attachClosingBraceMode)
{
if (isEmptyLine(formattedLine) || isImmediatelyPostPreprocessor
|| isCharImmediatelyPostLineComment
|| isCharImmediatelyPostComment)
appendCurrentChar(); else
{
appendSpacePad();
appendCurrentChar(false); }
}
else
{
if (!isBraceType(braceType, INIT_TYPE)
&& (!isBraceType(braceType, SINGLE_LINE_TYPE)
|| formattedLine.find('{') == string::npos))
breakLine();
appendCurrentChar();
}
char peekedChar = peekNextChar();
if (isLegalNameChar(peekedChar)
|| peekedChar == '[')
appendSpaceAfter();
}
}
void ASFormatter::formatRunIn()
{
assert(braceFormatMode == RUN_IN_MODE || braceFormatMode == NONE_MODE);
if (formattingStyle != STYLE_PICO
&& !isOkToBreakBlock(braceTypeStack->back()))
return;
size_t lastText = formattedLine.find_last_not_of(" \t");
if (lastText == string::npos || formattedLine[lastText] != '{')
return;
if (formattedLine.find_first_not_of(" \t{") != string::npos)
return;
if (isBraceType(braceTypeStack->back(), NAMESPACE_TYPE))
return;
bool extraIndent = false;
bool extraHalfIndent = false;
isInLineBreak = true;
if (isCStyle()
&& isCharPotentialHeader(currentLine, charNum)
&& (isBraceType(braceTypeStack->back(), CLASS_TYPE)
|| (isBraceType(braceTypeStack->back(), STRUCT_TYPE)
&& isInIndentableStruct)))
{
if (findKeyword(currentLine, charNum, AS_PUBLIC)
|| findKeyword(currentLine, charNum, AS_PRIVATE)
|| findKeyword(currentLine, charNum, AS_PROTECTED))
{
if (getModifierIndent())
extraHalfIndent = true;
else if (!getClassIndent())
return; }
else if (getClassIndent())
extraIndent = true;
}
if (!getSwitchIndent()
&& isCharPotentialHeader(currentLine, charNum)
&& (findKeyword(currentLine, charNum, AS_CASE)
|| findKeyword(currentLine, charNum, AS_DEFAULT)))
return;
if (getSwitchIndent()
&& !preBraceHeaderStack->empty()
&& preBraceHeaderStack->back() == &AS_SWITCH
&& ((isLegalNameChar(currentChar)
&& !findKeyword(currentLine, charNum, AS_CASE))))
extraIndent = true;
isInLineBreak = false;
if (formattedLine.length() > lastText + 1
&& formattedLine.find_first_not_of(" \t", lastText + 1) == string::npos)
formattedLine.erase(lastText + 1);
if (extraHalfIndent)
{
int indentLength_ = getIndentLength();
runInIndentChars = indentLength_ / 2;
formattedLine.append(runInIndentChars - 1, ' ');
}
else if (getForceTabIndentation() && getIndentLength() != getTabLength())
{
string indent;
int indentLength_ = getIndentLength();
int tabLength_ = getTabLength();
indent.append(indentLength_, ' ');
if (extraIndent)
indent.append(indentLength_, ' ');
size_t tabCount = indent.length() / tabLength_; indent.replace(0U, tabCount * tabLength_, tabCount, '\t');
runInIndentChars = indentLength_;
if (indent[0] == ' ') indent.erase(0, 1);
formattedLine.append(indent);
}
else if (getIndentString() == "\t")
{
appendChar('\t', false);
runInIndentChars = 2; if (extraIndent)
{
appendChar('\t', false);
runInIndentChars++;
}
}
else {
int indentLength_ = getIndentLength();
formattedLine.append(indentLength_ - 1, ' ');
runInIndentChars = indentLength_;
if (extraIndent)
{
formattedLine.append(indentLength_, ' ');
runInIndentChars += indentLength_;
}
}
isInBraceRunIn = true;
}
void ASFormatter::formatArrayRunIn()
{
assert(isBraceType(braceTypeStack->back(), ARRAY_TYPE));
if (formattedLine.find_first_not_of(" \t{") != string::npos)
return;
size_t lastText = formattedLine.find_last_not_of(" \t");
if (lastText == string::npos || formattedLine[lastText] != '{')
return;
if (formattedLine.length() > lastText + 1
&& formattedLine.find_first_not_of(" \t", lastText + 1) == string::npos)
formattedLine.erase(lastText + 1);
if (getIndentString() == "\t")
{
appendChar('\t', false);
runInIndentChars = 2; }
else
{
int indent = getIndentLength();
formattedLine.append(indent - 1, ' ');
runInIndentChars = indent;
}
isInBraceRunIn = true;
isInLineBreak = false;
}
void ASFormatter::deleteContainer(vector<BraceType>*& container)
{
if (container != nullptr)
{
container->clear();
delete (container);
container = nullptr;
}
}
template<typename T>
void ASFormatter::deleteContainer(T& container)
{
if (container != nullptr)
{
container->clear();
delete (container);
container = nullptr;
}
}
void ASFormatter::initContainer(vector<BraceType>*& container, vector<BraceType>* value)
{
if (container != nullptr)
deleteContainer(container);
container = value;
}
template<typename T>
void ASFormatter::initContainer(T& container, T value)
{
if (container != nullptr)
deleteContainer(container);
container = value;
}
void ASFormatter::convertTabToSpaces()
{
assert(currentChar == '\t');
if (isInQuote || isInQuoteContinuation)
return;
size_t tabSize = getTabLength();
size_t numSpaces = tabSize - ((tabIncrementIn + charNum) % tabSize);
currentLine.replace(charNum, 1, numSpaces, ' ');
currentChar = currentLine[charNum];
}
bool ASFormatter::isOkToBreakBlock(BraceType braceType) const
{
if (isBraceType(braceType, ARRAY_TYPE)
&& isBraceType(braceType, SINGLE_LINE_TYPE))
return false;
if (isBraceType(braceType, COMMAND_TYPE)
&& isBraceType(braceType, EMPTY_BLOCK_TYPE))
return false;
if (!isBraceType(braceType, SINGLE_LINE_TYPE)
|| isBraceType(braceType, BREAK_BLOCK_TYPE)
|| shouldBreakOneLineBlocks)
return true;
return false;
}
bool ASFormatter::isSharpStyleWithParen(const string* header) const
{
return (isSharpStyle() && peekNextChar() == '('
&& (header == &AS_CATCH
|| header == &AS_DELEGATE));
}
const string* ASFormatter::checkForHeaderFollowingComment(const string& firstLine) const
{
assert(isInComment || isInLineComment);
assert(shouldBreakElseIfs || shouldBreakBlocks || isInSwitchStatement());
bool endOnEmptyLine = (currentHeader == nullptr);
if (isInSwitchStatement())
endOnEmptyLine = false;
string nextText = peekNextText(firstLine, endOnEmptyLine);
if (nextText.length() == 0 || !isCharPotentialHeader(nextText, 0))
return nullptr;
return ASBase::findHeader(nextText, 0, headers);
}
void ASFormatter::processPreprocessor()
{
assert(currentChar == '#');
const size_t preproc = currentLine.find_first_not_of(" \t", charNum + 1);
if (preproc == string::npos)
return;
if (currentLine.compare(preproc, 2, "if") == 0)
{
preprocBraceTypeStackSize = braceTypeStack->size();
}
else if (currentLine.compare(preproc, 4, "else") == 0)
{
if (preprocBraceTypeStackSize > 0)
{
int addedPreproc = braceTypeStack->size() - preprocBraceTypeStackSize;
for (int i = 0; i < addedPreproc; i++)
braceTypeStack->pop_back();
}
}
}
bool ASFormatter::commentAndHeaderFollows()
{
assert(shouldDeleteEmptyLines && shouldBreakBlocks);
auto stream = make_shared<ASPeekStream>(sourceIterator);
if (!stream->hasMoreLines())
return false;
string nextLine_ = stream->peekNextLine();
size_t firstChar = nextLine_.find_first_not_of(" \t");
if (firstChar == string::npos
|| !(nextLine_.compare(firstChar, 2, "//") == 0
|| nextLine_.compare(firstChar, 2, "/*") == 0))
return false;
string nextText = peekNextText(nextLine_, false, stream);
if (nextText.length() == 0 || !isCharPotentialHeader(nextText, 0))
return false;
const string* newHeader = ASBase::findHeader(nextText, 0, headers);
if (newHeader == nullptr)
return false;
if (isClosingHeader(newHeader) && !shouldBreakClosingHeaderBlocks)
{
isAppendPostBlockEmptyLineRequested = false;
return false;
}
return true;
}
bool ASFormatter::isCurrentBraceBroken() const
{
assert(braceTypeStack->size() > 1);
bool breakBrace = false;
size_t stackEnd = braceTypeStack->size() - 1;
if (shouldAttachExternC
&& isBraceType((*braceTypeStack)[stackEnd], EXTERN_TYPE))
{
return false;
}
if (shouldAttachNamespace
&& isBraceType((*braceTypeStack)[stackEnd], NAMESPACE_TYPE))
{
return false;
}
if (shouldAttachClass
&& (isBraceType((*braceTypeStack)[stackEnd], CLASS_TYPE)
|| isBraceType((*braceTypeStack)[stackEnd], INTERFACE_TYPE)))
{
return false;
}
if (shouldAttachInline
&& isCStyle() && braceFormatMode != RUN_IN_MODE
&& !(currentLineBeginsWithBrace && peekNextChar() == '/')
&& isBraceType((*braceTypeStack)[stackEnd], COMMAND_TYPE))
{
size_t i;
for (i = 1; i < braceTypeStack->size(); i++)
if (isBraceType((*braceTypeStack)[i], CLASS_TYPE)
|| isBraceType((*braceTypeStack)[i], STRUCT_TYPE))
return false;
}
if (isBraceType((*braceTypeStack)[stackEnd], EXTERN_TYPE))
{
if (currentLineBeginsWithBrace
|| braceFormatMode == RUN_IN_MODE)
breakBrace = true;
}
else if (braceFormatMode == NONE_MODE)
{
if (currentLineBeginsWithBrace
&& (int) currentLineFirstBraceNum == charNum)
breakBrace = true;
}
else if (braceFormatMode == BREAK_MODE || braceFormatMode == RUN_IN_MODE)
{
breakBrace = true;
}
else if (braceFormatMode == LINUX_MODE)
{
if (isBraceType((*braceTypeStack)[stackEnd], NAMESPACE_TYPE))
{
if (formattingStyle != STYLE_STROUSTRUP
&& formattingStyle != STYLE_MOZILLA)
breakBrace = true;
}
else if (isBraceType((*braceTypeStack)[stackEnd], CLASS_TYPE)
|| isBraceType((*braceTypeStack)[stackEnd], INTERFACE_TYPE))
{
if (formattingStyle != STYLE_STROUSTRUP)
breakBrace = true;
}
else if (isBraceType((*braceTypeStack)[stackEnd], STRUCT_TYPE))
{
if (formattingStyle == STYLE_MOZILLA)
breakBrace = true;
}
else if (isBraceType((*braceTypeStack)[stackEnd], COMMAND_TYPE))
{
if (stackEnd == 1)
{
breakBrace = true;
}
else if (stackEnd > 1)
{
if (isBraceType((*braceTypeStack)[stackEnd - 1], NAMESPACE_TYPE)
|| isBraceType((*braceTypeStack)[stackEnd - 1], CLASS_TYPE)
|| isBraceType((*braceTypeStack)[stackEnd - 1], ARRAY_TYPE)
|| isBraceType((*braceTypeStack)[stackEnd - 1], STRUCT_TYPE)
|| isBraceType((*braceTypeStack)[stackEnd - 1], EXTERN_TYPE))
{
breakBrace = true;
}
}
}
}
return breakBrace;
}
void ASFormatter::formatCommentBody()
{
assert(isInComment);
while (charNum < (int) currentLine.length())
{
currentChar = currentLine[charNum];
if (isSequenceReached("*/"))
{
formatCommentCloser();
break;
}
if (currentChar == '\t' && shouldConvertTabs)
convertTabToSpaces();
appendCurrentChar();
++charNum;
}
if (shouldStripCommentPrefix)
stripCommentPrefix();
}
void ASFormatter::formatCommentOpener()
{
assert(isSequenceReached("/*"));
isInComment = isInCommentStartLine = true;
isImmediatelyPostLineComment = false;
if (previousNonWSChar == '}')
resetEndOfStatement();
const string* followingHeader = nullptr;
if ((doesLineStartComment
&& !isImmediatelyPostCommentOnly
&& isBraceType(braceTypeStack->back(), COMMAND_TYPE))
&& (shouldBreakElseIfs
|| isInSwitchStatement()
|| (shouldBreakBlocks
&& !isImmediatelyPostEmptyLine
&& previousCommandChar != '{')))
followingHeader = checkForHeaderFollowingComment(currentLine.substr(charNum));
if (spacePadNum != 0 && !isInLineBreak)
adjustComments();
formattedLineCommentNum = formattedLine.length();
if (previousCommandChar == '{'
&& !isImmediatelyPostComment
&& !isImmediatelyPostLineComment)
{
if (isBraceType(braceTypeStack->back(), NAMESPACE_TYPE))
{
isInLineBreak = true;
}
else if (braceFormatMode == NONE_MODE)
{
if (currentLineBeginsWithBrace)
formatRunIn();
}
else if (braceFormatMode == ATTACH_MODE)
{
if (formattedLine.length() > 0 && formattedLine[0] == '{'
&& !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE))
isInLineBreak = true;
}
else if (braceFormatMode == RUN_IN_MODE)
{
if (formattedLine.length() > 0 && formattedLine[0] == '{')
formatRunIn();
}
}
else if (!doesLineStartComment)
noTrimCommentContinuation = true;
if (shouldBreakElseIfs && followingHeader == &AS_ELSE)
elseHeaderFollowsComments = true;
if (followingHeader == &AS_CASE || followingHeader == &AS_DEFAULT)
caseHeaderFollowsComments = true;
appendSequence(AS_OPEN_COMMENT);
goForward(1);
if (shouldBreakBlocks
&& followingHeader != nullptr
&& !isImmediatelyPostEmptyLine
&& previousCommandChar != '{')
{
if (isClosingHeader(followingHeader))
{
if (!shouldBreakClosingHeaderBlocks)
isPrependPostBlockEmptyLineRequested = false;
}
else
isPrependPostBlockEmptyLineRequested = true;
}
if (previousCommandChar == '}')
currentHeader = nullptr;
}
void ASFormatter::formatCommentCloser()
{
assert(isSequenceReached("*/"));
isInComment = false;
noTrimCommentContinuation = false;
isImmediatelyPostComment = true;
appendSequence(AS_CLOSE_COMMENT);
goForward(1);
if (doesLineStartComment
&& (currentLine.find_first_not_of(" \t", charNum + 1) == string::npos))
lineEndsInCommentOnly = true;
if (peekNextChar() == '}'
&& previousCommandChar != ';'
&& !isBraceType(braceTypeStack->back(), ARRAY_TYPE)
&& !isInPreprocessor
&& isOkToBreakBlock(braceTypeStack->back()))
{
isInLineBreak = true;
shouldBreakLineAtNextChar = true;
}
}
void ASFormatter::formatLineCommentBody()
{
assert(isInLineComment);
while (charNum < (int) currentLine.length())
{
currentChar = currentLine[charNum];
if (currentChar == '\t' && shouldConvertTabs)
convertTabToSpaces();
appendCurrentChar();
++charNum;
}
if (charNum == (int) currentLine.length())
{
isInLineBreak = true;
isInLineComment = false;
isImmediatelyPostLineComment = true;
currentChar = 0; }
}
void ASFormatter::formatLineCommentOpener()
{
assert(isSequenceReached("//"));
if ((int) currentLine.length() > charNum + 2
&& currentLine[charNum + 2] == '\xf2') isAppendPostBlockEmptyLineRequested = false;
isInLineComment = true;
isCharImmediatelyPostComment = false;
if (previousNonWSChar == '}')
resetEndOfStatement();
const string* followingHeader = nullptr;
if ((lineIsLineCommentOnly
&& !isImmediatelyPostCommentOnly
&& isBraceType(braceTypeStack->back(), COMMAND_TYPE))
&& (shouldBreakElseIfs
|| isInSwitchStatement()
|| (shouldBreakBlocks
&& !isImmediatelyPostEmptyLine
&& previousCommandChar != '{')))
followingHeader = checkForHeaderFollowingComment(currentLine.substr(charNum));
if ((!shouldIndentCol1Comments && !lineCommentNoIndent)
|| foundNamespaceHeader)
{
if (charNum == 0)
lineCommentNoIndent = true;
else if (charNum == 1 && currentLine[0] == ' ')
lineCommentNoIndent = true;
}
if (!lineCommentNoIndent && spacePadNum != 0 && !isInLineBreak)
adjustComments();
formattedLineCommentNum = formattedLine.length();
if (previousCommandChar == '{'
&& !isImmediatelyPostComment
&& !isImmediatelyPostLineComment)
{
if (braceFormatMode == NONE_MODE)
{
if (currentLineBeginsWithBrace)
formatRunIn();
}
else if (braceFormatMode == RUN_IN_MODE)
{
if (!lineCommentNoIndent)
formatRunIn();
else
isInLineBreak = true;
}
else if (braceFormatMode == BREAK_MODE)
{
if (formattedLine.length() > 0 && formattedLine[0] == '{')
isInLineBreak = true;
}
else
{
if (currentLineBeginsWithBrace)
isInLineBreak = true;
}
}
if (shouldBreakElseIfs && followingHeader == &AS_ELSE)
elseHeaderFollowsComments = true;
if (followingHeader == &AS_CASE || followingHeader == &AS_DEFAULT)
caseHeaderFollowsComments = true;
appendSequence(AS_OPEN_LINE_COMMENT);
goForward(1);
if (shouldBreakBlocks
&& followingHeader != nullptr
&& !isImmediatelyPostEmptyLine
&& previousCommandChar != '{')
{
if (isClosingHeader(followingHeader))
{
if (!shouldBreakClosingHeaderBlocks)
isPrependPostBlockEmptyLineRequested = false;
}
else
isPrependPostBlockEmptyLineRequested = true;
}
if (previousCommandChar == '}')
currentHeader = nullptr;
if (getIndentString() == "\t" && lineCommentNoIndent)
{
while (charNum + 1 < (int) currentLine.length()
&& currentLine[charNum + 1] == '\t')
{
currentChar = currentLine[++charNum];
appendCurrentChar();
}
}
if (charNum + 1 == (int) currentLine.length())
{
isInLineBreak = true;
isInLineComment = false;
isImmediatelyPostLineComment = true;
currentChar = 0; }
}
void ASFormatter::formatQuoteBody()
{
assert(isInQuote);
if (isSpecialChar)
{
isSpecialChar = false;
}
else if (currentChar == '\\' && !isInVerbatimQuote)
{
if (peekNextChar() == ' ') haveLineContinuationChar = true;
else
isSpecialChar = true;
}
else if (isInVerbatimQuote && currentChar == '"')
{
if (isCStyle())
{
string delim = ')' + verbatimDelimiter;
int delimStart = charNum - delim.length();
if (delimStart > 0 && currentLine.substr(delimStart, delim.length()) == delim)
{
isInQuote = false;
isInVerbatimQuote = false;
}
}
else if (isSharpStyle())
{
if ((int) currentLine.length() > charNum + 1
&& currentLine[charNum + 1] == '"') {
appendSequence("\"\"");
goForward(1);
return;
}
isInQuote = false;
isInVerbatimQuote = false;
}
}
else if (quoteChar == currentChar)
{
isInQuote = false;
}
appendCurrentChar();
if (isInQuote && currentChar != '\\')
{
while (charNum + 1 < (int) currentLine.length()
&& currentLine[charNum + 1] != quoteChar
&& currentLine[charNum + 1] != '\\')
{
currentChar = currentLine[++charNum];
appendCurrentChar();
}
}
if (charNum + 1 >= (int) currentLine.length()
&& currentChar != '\\'
&& !isInVerbatimQuote)
isInQuote = false; }
void ASFormatter::formatQuoteOpener()
{
assert(currentChar == '"'
|| (currentChar == '\'' && !isDigitSeparator(currentLine, charNum)));
isInQuote = true;
quoteChar = currentChar;
if (isCStyle() && previousChar == 'R')
{
int parenPos = currentLine.find('(', charNum);
if (parenPos != -1)
{
isInVerbatimQuote = true;
verbatimDelimiter = currentLine.substr(charNum + 1, parenPos - charNum - 1);
}
}
else if (isSharpStyle() && previousChar == '@')
isInVerbatimQuote = true;
if (previousCommandChar == '{'
&& !isImmediatelyPostComment
&& !isImmediatelyPostLineComment
&& isNonInStatementArray
&& !isBraceType(braceTypeStack->back(), SINGLE_LINE_TYPE)
&& !isWhiteSpace(peekNextChar()))
{
if (braceFormatMode == NONE_MODE)
{
if (currentLineBeginsWithBrace)
formatRunIn();
}
else if (braceFormatMode == RUN_IN_MODE)
{
formatRunIn();
}
else if (braceFormatMode == BREAK_MODE)
{
if (formattedLine.length() > 0 && formattedLine[0] == '{')
isInLineBreak = true;
}
else
{
if (currentLineBeginsWithBrace)
isInLineBreak = true;
}
}
previousCommandChar = ' ';
appendCurrentChar();
}
int ASFormatter::getNextLineCommentAdjustment()
{
assert(foundClosingHeader && previousNonWSChar == '}');
if (charNum < 1) return 0;
size_t lastBrace = currentLine.rfind('}', charNum - 1);
if (lastBrace != string::npos)
return (lastBrace - charNum); return 0;
}
LineEndFormat ASFormatter::getLineEndFormat() const
{
return lineEnd;
}
int ASFormatter::getCurrentLineCommentAdjustment()
{
assert(foundClosingHeader && previousNonWSChar == '}');
if (charNum < 1)
return 2;
size_t lastBrace = currentLine.rfind('}', charNum - 1);
if (lastBrace == string::npos)
return 2;
return 0;
}
string ASFormatter::getPreviousWord(const string& line, int currPos) const
{
if (currPos == 0)
return string();
size_t end = line.find_last_not_of(" \t", currPos - 1);
if (end == string::npos || !isLegalNameChar(line[end]))
return string();
int start; for (start = end; start > -1; start--)
{
if (!isLegalNameChar(line[start]) || line[start] == '.')
break;
}
start++;
return (line.substr(start, end - start + 1));
}
void ASFormatter::isLineBreakBeforeClosingHeader()
{
assert(foundClosingHeader && previousNonWSChar == '}');
if (currentHeader == &AS_WHILE && shouldAttachClosingWhile)
{
appendClosingHeader();
return;
}
if (braceFormatMode == BREAK_MODE
|| braceFormatMode == RUN_IN_MODE
|| attachClosingBraceMode)
{
isInLineBreak = true;
}
else if (braceFormatMode == NONE_MODE)
{
if (shouldBreakClosingHeaderBraces
|| getBraceIndent() || getBlockIndent())
{
isInLineBreak = true;
}
else
{
appendSpacePad();
size_t i = currentLine.find_first_not_of(" \t");
if (i != string::npos && currentLine[i] == '}')
isInLineBreak = false;
if (shouldBreakBlocks)
isAppendPostBlockEmptyLineRequested = false;
}
}
else
{
if (shouldBreakClosingHeaderBraces
|| getBraceIndent() || getBlockIndent())
{
isInLineBreak = true;
}
else
{
appendClosingHeader();
if (shouldBreakBlocks)
isAppendPostBlockEmptyLineRequested = false;
}
}
}
void ASFormatter::appendClosingHeader()
{
bool previousLineIsEmpty = isEmptyLine(formattedLine);
int previousLineIsOneLineBlock = 0;
size_t firstBrace = findNextChar(formattedLine, '{');
if (firstBrace != string::npos)
previousLineIsOneLineBlock = isOneLineBlockReached(formattedLine, firstBrace);
if (!previousLineIsEmpty
&& previousLineIsOneLineBlock == 0)
{
isInLineBreak = false;
appendSpacePad();
spacePadNum = 0; }
}
bool ASFormatter::addBracesToStatement()
{
assert(isImmediatelyPostHeader);
if (currentHeader != &AS_IF
&& currentHeader != &AS_ELSE
&& currentHeader != &AS_FOR
&& currentHeader != &AS_WHILE
&& currentHeader != &AS_DO
&& currentHeader != &AS_FOREACH
&& currentHeader != &AS_QFOREACH
&& currentHeader != &AS_QFOREVER
&& currentHeader != &AS_FOREVER)
return false;
if (currentHeader == &AS_WHILE && foundClosingHeader) return false;
if (currentChar == ';')
return false;
if (isCharPotentialHeader(currentLine, charNum))
if (findHeader(headers) != nullptr)
return false;
size_t nextSemiColon = charNum;
if (currentChar != ';')
nextSemiColon = findNextChar(currentLine, ';', charNum + 1);
if (nextSemiColon == string::npos)
return false;
if (nextSemiColon == currentLine.length() - 1)
currentLine.append(" }");
else
currentLine.insert(nextSemiColon + 1, " }");
currentLine.insert(charNum, "{ ");
assert(computeChecksumIn("{}"));
currentChar = '{';
if ((int) currentLine.find_first_not_of(" \t") == charNum)
currentLineBeginsWithBrace = true;
if (!shouldAddOneLineBraces)
{
size_t lastText = formattedLine.find_last_not_of(" \t");
if ((formattedLine.length() - 1) - lastText > 1)
formattedLine.erase(lastText + 1);
}
return true;
}
bool ASFormatter::removeBracesFromStatement()
{
assert(isImmediatelyPostHeader);
assert(currentChar == '{');
if (currentHeader != &AS_IF
&& currentHeader != &AS_ELSE
&& currentHeader != &AS_FOR
&& currentHeader != &AS_WHILE
&& currentHeader != &AS_FOREACH)
return false;
if (currentHeader == &AS_WHILE && foundClosingHeader) return false;
bool isFirstLine = true;
string nextLine_;
if (!isBeforeAnyLineEndComment(charNum) || currentLineBeginsWithBrace)
nextLine_ = currentLine.substr(charNum + 1);
size_t nextChar = 0;
ASPeekStream stream(sourceIterator);
while (stream.hasMoreLines() || isFirstLine)
{
if (isFirstLine)
isFirstLine = false;
else
{
nextLine_ = stream.peekNextLine();
nextChar = 0;
}
nextChar = nextLine_.find_first_not_of(" \t", nextChar);
if (nextChar != string::npos)
break;
}
if ((nextLine_.compare(nextChar, 2, "/*") == 0)
|| (nextLine_.compare(nextChar, 2, "//") == 0)
|| (isCharPotentialHeader(nextLine_, nextChar)
&& ASBase::findHeader(nextLine_, nextChar, headers) != nullptr))
return false;
size_t nextSemiColon = nextChar;
if (nextLine_[nextChar] != ';')
nextSemiColon = findNextChar(nextLine_, ';', nextChar + 1);
if (nextSemiColon == string::npos)
return false;
isFirstLine = true;
nextChar = nextSemiColon + 1;
while (stream.hasMoreLines() || isFirstLine)
{
if (isFirstLine)
isFirstLine = false;
else
{
nextLine_ = stream.peekNextLine();
nextChar = 0;
}
nextChar = nextLine_.find_first_not_of(" \t", nextChar);
if (nextChar != string::npos)
break;
}
if (nextLine_.length() == 0 || nextLine_[nextChar] != '}')
return false;
currentLine[charNum] = currentChar = ' ';
assert(adjustChecksumIn(-'{'));
return true;
}
size_t ASFormatter::findNextChar(const string& line, char searchChar, int searchStart ) const
{
size_t i;
for (i = searchStart; i < line.length(); i++)
{
if (line.compare(i, 2, "//") == 0)
return string::npos;
if (line.compare(i, 2, "/*") == 0)
{
size_t endComment = line.find("*/", i + 2);
if (endComment == string::npos)
return string::npos;
i = endComment + 2;
if (i >= line.length())
return string::npos;
}
if (line[i] == '"'
|| (line[i] == '\'' && !isDigitSeparator(line, i)))
{
char quote = line[i];
while (i < line.length())
{
size_t endQuote = line.find(quote, i + 1);
if (endQuote == string::npos)
return string::npos;
i = endQuote;
if (line[endQuote - 1] != '\\') break;
if (line[endQuote - 2] == '\\') break;
}
}
if (line[i] == searchChar)
break;
if (line[i] == '{')
return string::npos;
}
if (i >= line.length()) return string::npos;
return i;
}
bool ASFormatter::isStructAccessModified(const string& firstLine, size_t index) const
{
assert(firstLine[index] == '{');
assert(isCStyle());
bool isFirstLine = true;
size_t braceCount = 1;
string nextLine_ = firstLine.substr(index + 1);
ASPeekStream stream(sourceIterator);
bool isInComment_ = false;
bool isInQuote_ = false;
char quoteChar_ = ' ';
while (stream.hasMoreLines() || isFirstLine)
{
if (isFirstLine)
isFirstLine = false;
else
nextLine_ = stream.peekNextLine();
for (size_t i = 0; i < nextLine_.length(); i++)
{
if (isWhiteSpace(nextLine_[i]))
continue;
if (nextLine_.compare(i, 2, "/*") == 0)
isInComment_ = true;
if (isInComment_)
{
if (nextLine_.compare(i, 2, "*/") == 0)
{
isInComment_ = false;
++i;
}
continue;
}
if (nextLine_[i] == '\\')
{
++i;
continue;
}
if (isInQuote_)
{
if (nextLine_[i] == quoteChar_)
isInQuote_ = false;
continue;
}
if (nextLine_[i] == '"'
|| (nextLine_[i] == '\'' && !isDigitSeparator(nextLine_, i)))
{
isInQuote_ = true;
quoteChar_ = nextLine_[i];
continue;
}
if (nextLine_.compare(i, 2, "//") == 0)
{
i = nextLine_.length();
continue;
}
if (nextLine_[i] == '{')
++braceCount;
if (nextLine_[i] == '}')
--braceCount;
if (braceCount == 0)
return false;
if (isCharPotentialHeader(nextLine_, i))
{
if (findKeyword(nextLine_, i, AS_PUBLIC)
|| findKeyword(nextLine_, i, AS_PRIVATE)
|| findKeyword(nextLine_, i, AS_PROTECTED))
return true;
string name = getCurrentWord(nextLine_, i);
i += name.length() - 1;
}
} }
return false;
}
bool ASFormatter::isIndentablePreprocessorBlock(const string& firstLine, size_t index)
{
assert(firstLine[index] == '#');
bool isFirstLine = true;
bool isInIndentableBlock = false;
bool blockContainsBraces = false;
bool blockContainsDefineContinuation = false;
bool isInClassConstructor = false;
bool isPotentialHeaderGuard = false; bool isPotentialHeaderGuard2 = false; int numBlockIndents = 0;
int lineParenCount = 0;
string nextLine_ = firstLine.substr(index);
auto stream = make_shared<ASPeekStream>(sourceIterator);
bool isInComment_ = false;
bool isInQuote_ = false;
char quoteChar_ = ' ';
while (stream->hasMoreLines() || isFirstLine)
{
if (isFirstLine)
isFirstLine = false;
else
nextLine_ = stream->peekNextLine();
for (size_t i = 0; i < nextLine_.length(); i++)
{
if (isWhiteSpace(nextLine_[i]))
continue;
if (nextLine_.compare(i, 2, "/*") == 0)
isInComment_ = true;
if (isInComment_)
{
if (nextLine_.compare(i, 2, "*/") == 0)
{
isInComment_ = false;
++i;
}
continue;
}
if (nextLine_[i] == '\\')
{
++i;
continue;
}
if (isInQuote_)
{
if (nextLine_[i] == quoteChar_)
isInQuote_ = false;
continue;
}
if (nextLine_[i] == '"'
|| (nextLine_[i] == '\'' && !isDigitSeparator(nextLine_, i)))
{
isInQuote_ = true;
quoteChar_ = nextLine_[i];
continue;
}
if (nextLine_.compare(i, 2, "//") == 0)
{
i = nextLine_.length();
continue;
}
if (nextLine_[i] == '#')
{
string preproc = ASBeautifier::extractPreprocessorStatement(nextLine_);
if (preproc.length() >= 2 && preproc.substr(0, 2) == "if") {
numBlockIndents += 1;
isInIndentableBlock = true;
if (!processedFirstConditional)
{
processedFirstConditional = true;
isFirstPreprocConditional = true;
if (isNDefPreprocStatement(nextLine_, preproc))
isPotentialHeaderGuard = true;
}
}
else if (preproc == "endif")
{
if (numBlockIndents > 0)
numBlockIndents -= 1;
if (numBlockIndents == 0)
goto EndOfWhileLoop;
}
else if (preproc == "define")
{
if (nextLine_[nextLine_.length() - 1] == '\\')
blockContainsDefineContinuation = true;
else if (isPotentialHeaderGuard && numBlockIndents == 1)
isPotentialHeaderGuard2 = true;
}
i = nextLine_.length();
continue;
}
if (nextLine_[i] == '{' || nextLine_[i] == '}')
blockContainsBraces = true;
else if (nextLine_[i] == '(')
++lineParenCount;
else if (nextLine_[i] == ')')
--lineParenCount;
else if (nextLine_[i] == ':')
{
if (nextLine_.length() > i && nextLine_[i + 1] == ':')
++i;
else
isInClassConstructor = true;
}
if (blockContainsBraces || isInClassConstructor || blockContainsDefineContinuation)
goto EndOfWhileLoop;
} if (lineParenCount != 0)
break;
} EndOfWhileLoop:
preprocBlockEnd = sourceIterator->tellg();
if (preprocBlockEnd < 0)
preprocBlockEnd = sourceIterator->getStreamLength();
if (blockContainsBraces
|| isInClassConstructor
|| blockContainsDefineContinuation
|| lineParenCount != 0
|| numBlockIndents != 0)
isInIndentableBlock = false;
string nextText = peekNextText("", false, stream);
if (isFirstPreprocConditional)
{
isFirstPreprocConditional = false;
if (nextText.empty() && isPotentialHeaderGuard2)
{
isInIndentableBlock = false;
preprocBlockEnd = 0;
}
}
if (!isInIndentableBlock)
preprocBlockEnd = 0;
return isInIndentableBlock;
}
bool ASFormatter::isNDefPreprocStatement(const string& nextLine_, const string& preproc) const
{
if (preproc == "ifndef")
return true;
if (preproc == "if")
{
size_t i = nextLine_.find('!');
if (i == string::npos)
return false;
i = nextLine_.find_first_not_of(" \t", ++i);
if (i != string::npos && nextLine_.compare(i, 7, "defined") == 0)
return true;
}
return false;
}
bool ASFormatter::isExecSQL(const string& line, size_t index) const
{
if (line[index] != 'e' && line[index] != 'E') return false;
string word;
if (isCharPotentialHeader(line, index))
word = getCurrentWord(line, index);
for (size_t i = 0; i < word.length(); i++)
word[i] = (char) toupper(word[i]);
if (word != "EXEC")
return false;
size_t index2 = index + word.length();
index2 = line.find_first_not_of(" \t", index2);
if (index2 == string::npos)
return false;
word.erase();
if (isCharPotentialHeader(line, index2))
word = getCurrentWord(line, index2);
for (size_t i = 0; i < word.length(); i++)
word[i] = (char) toupper(word[i]);
if (word != "SQL")
return false;
return true;
}
void ASFormatter::trimContinuationLine()
{
size_t len = currentLine.length();
size_t tabSize = getTabLength();
charNum = 0;
if (leadingSpaces > 0 && len > 0)
{
size_t i;
size_t continuationIncrementIn = 0;
for (i = 0; (i < len) && (i + continuationIncrementIn < leadingSpaces); i++)
{
if (!isWhiteSpace(currentLine[i])) {
if (i < continuationIncrementIn)
leadingSpaces = i + tabIncrementIn;
continuationIncrementIn = tabIncrementIn;
break;
}
if (currentLine[i] == '\t')
continuationIncrementIn += tabSize - 1 - ((continuationIncrementIn + i) % tabSize);
}
if ((int) continuationIncrementIn == tabIncrementIn)
charNum = i;
else
{
string newLine;
int leadingChars = 0;
if ((int) leadingSpaces > tabIncrementIn)
leadingChars = leadingSpaces - tabIncrementIn;
newLine.append(leadingChars, ' ');
newLine.append(currentLine, i, len - i);
currentLine = newLine;
charNum = leadingChars;
if (currentLine.length() == 0)
currentLine = string(" "); }
if (i >= len)
charNum = 0;
}
}
bool ASFormatter::isClosingHeader(const string* header) const
{
return (header == &AS_ELSE
|| header == &AS_CATCH
|| header == &AS_FINALLY);
}
bool ASFormatter::isImmediatelyPostCast() const
{
assert(previousNonWSChar == ')' && currentChar == '*');
string line; size_t paren = currentLine.rfind(')', charNum);
if (paren != string::npos)
line = currentLine;
else
{
line = readyFormattedLine;
paren = line.rfind(')');
if (paren == string::npos)
return false;
}
if (paren == 0)
return false;
size_t lastChar = line.find_last_not_of(" \t", paren - 1);
if (lastChar == string::npos)
return false;
if (line[lastChar] == '*')
return true;
return false;
}
void ASFormatter::checkIfTemplateOpener()
{
assert(!isInTemplate && currentChar == '<');
size_t firstChar = currentLine.find_first_not_of("< \t", charNum);
if (firstChar == string::npos
|| currentLine[firstChar] == '=')
{
isInTemplate = false;
return;
}
bool isFirstLine = true;
int parenDepth_ = 0;
int maxTemplateDepth = 0;
templateDepth = 0;
string nextLine_ = currentLine.substr(charNum);
ASPeekStream stream(sourceIterator);
bool isInComment_ = false;
bool isInQuote_ = false;
char quoteChar_ = ' ';
while (stream.hasMoreLines() || isFirstLine)
{
if (isFirstLine)
isFirstLine = false;
else
nextLine_ = stream.peekNextLine();
for (size_t i = 0; i < nextLine_.length(); i++)
{
char currentChar_ = nextLine_[i];
if (isWhiteSpace(currentChar_))
continue;
if (nextLine_.compare(i, 2, "/*") == 0)
isInComment_ = true;
if (isInComment_)
{
if (nextLine_.compare(i, 2, "*/") == 0)
{
isInComment_ = false;
++i;
}
continue;
}
if (currentChar_ == '\\')
{
++i;
continue;
}
if (isInQuote_)
{
if (currentChar_ == quoteChar_)
isInQuote_ = false;
continue;
}
if (currentChar_ == '"'
|| (currentChar_ == '\'' && !isDigitSeparator(nextLine_, i)))
{
isInQuote_ = true;
quoteChar_ = currentChar_;
continue;
}
if (nextLine_.compare(i, 2, "//") == 0)
{
i = nextLine_.length();
continue;
}
if (currentChar_ == '<')
{
++templateDepth;
++maxTemplateDepth;
continue;
}
else if (currentChar_ == '>')
{
--templateDepth;
if (templateDepth == 0)
{
if (parenDepth_ == 0)
{
isInTemplate = true;
templateDepth = maxTemplateDepth;
}
return;
}
continue;
}
else if (currentChar_ == '(' || currentChar_ == ')')
{
if (currentChar_ == '(')
++parenDepth_;
else
--parenDepth_;
if (parenDepth_ >= 0)
continue;
isInTemplate = false;
templateDepth = 0;
return;
}
else if (nextLine_.compare(i, 2, AS_AND) == 0
|| nextLine_.compare(i, 2, AS_OR) == 0)
{
isInTemplate = false;
templateDepth = 0;
return;
}
else if (currentChar_ == ',' || currentChar_ == '&' || currentChar_ == '*' || currentChar_ == '^' || currentChar_ == ':' || currentChar_ == '=' || currentChar_ == '[' || currentChar_ == ']' || currentChar_ == '(' || currentChar_ == ')' || (isJavaStyle() && currentChar_ == '?') )
{
continue;
}
else if (!isLegalNameChar(currentChar_))
{
isInTemplate = false;
templateDepth = 0;
return;
}
string name = getCurrentWord(nextLine_, i);
i += name.length() - 1;
} } }
void ASFormatter::updateFormattedLineSplitPoints(char appendedChar)
{
assert(maxCodeLength != string::npos);
assert(formattedLine.length() > 0);
if (!isOkToSplitFormattedLine())
return;
char nextChar = peekNextChar();
if (nextChar == '/')
return;
if (appendedChar == '{' || appendedChar == '}'
|| previousNonWSChar == '{' || previousNonWSChar == '}'
|| nextChar == '{' || nextChar == '}'
|| currentChar == '{' || currentChar == '}') return;
if (appendedChar == '[' || appendedChar == ']'
|| previousNonWSChar == '['
|| nextChar == '[' || nextChar == ']')
return;
if (isWhiteSpace(appendedChar))
{
if (nextChar != ')' && nextChar != '(' && nextChar != '/' && nextChar != ':' && currentChar != ')' && currentChar != '(' && previousNonWSChar != '(' && !(nextChar == '*'
&& !isCharPotentialOperator(previousNonWSChar)
&& pointerAlignment == PTR_ALIGN_TYPE)
&& !(nextChar == '&'
&& !isCharPotentialOperator(previousNonWSChar)
&& (referenceAlignment == REF_ALIGN_TYPE
|| (referenceAlignment == REF_SAME_AS_PTR && pointerAlignment == PTR_ALIGN_TYPE)))
)
{
if (formattedLine.length() - 1 <= maxCodeLength)
maxWhiteSpace = formattedLine.length() - 1;
else
maxWhiteSpacePending = formattedLine.length() - 1;
}
}
else if (appendedChar == ')')
{
if (nextChar != ')'
&& nextChar != ' '
&& nextChar != ';'
&& nextChar != ','
&& nextChar != '.'
&& !(nextChar == '-' && pointerSymbolFollows())) {
if (formattedLine.length() <= maxCodeLength)
maxWhiteSpace = formattedLine.length();
else
maxWhiteSpacePending = formattedLine.length();
}
}
else if (appendedChar == ',')
{
if (formattedLine.length() <= maxCodeLength)
maxComma = formattedLine.length();
else
maxCommaPending = formattedLine.length();
}
else if (appendedChar == '(')
{
if (nextChar != ')' && nextChar != '(' && nextChar != '"' && nextChar != '\'')
{
size_t parenNum;
if (isCharPotentialOperator(previousNonWSChar))
parenNum = formattedLine.length() - 1;
else
parenNum = formattedLine.length();
if (formattedLine.length() <= maxCodeLength)
maxParen = parenNum;
else
maxParenPending = parenNum;
}
}
else if (appendedChar == ';')
{
if (nextChar != ' ' && nextChar != '}' && nextChar != '/') {
if (formattedLine.length() <= maxCodeLength)
maxSemi = formattedLine.length();
else
maxSemiPending = formattedLine.length();
}
}
}
void ASFormatter::updateFormattedLineSplitPointsOperator(const string& sequence)
{
assert(maxCodeLength != string::npos);
assert(formattedLine.length() > 0);
if (!isOkToSplitFormattedLine())
return;
char nextChar = peekNextChar();
if (nextChar == '/')
return;
if (sequence == "||" || sequence == "&&" || sequence == "or" || sequence == "and")
{
if (shouldBreakLineAfterLogical)
{
if (formattedLine.length() <= maxCodeLength)
maxAndOr = formattedLine.length();
else
maxAndOrPending = formattedLine.length();
}
else
{
size_t sequenceLength = sequence.length();
if (formattedLine.length() > sequenceLength
&& isWhiteSpace(formattedLine[formattedLine.length() - sequenceLength - 1]))
sequenceLength++;
if (formattedLine.length() - sequenceLength <= maxCodeLength)
maxAndOr = formattedLine.length() - sequenceLength;
else
maxAndOrPending = formattedLine.length() - sequenceLength;
}
}
else if (sequence == "==" || sequence == "!=" || sequence == ">=" || sequence == "<=")
{
if (formattedLine.length() <= maxCodeLength)
maxWhiteSpace = formattedLine.length();
else
maxWhiteSpacePending = formattedLine.length();
}
else if (sequence == "+" || sequence == "-" || sequence == "?")
{
if (charNum > 0
&& !(sequence == "+" && isInExponent())
&& !(sequence == "-" && isInExponent())
&& (isLegalNameChar(currentLine[charNum - 1])
|| currentLine[charNum - 1] == ')'
|| currentLine[charNum - 1] == ']'
|| currentLine[charNum - 1] == '\"'))
{
if (formattedLine.length() - 1 <= maxCodeLength)
maxWhiteSpace = formattedLine.length() - 1;
else
maxWhiteSpacePending = formattedLine.length() - 1;
}
}
else if (sequence == "=" || sequence == ":")
{
size_t splitPoint = 0;
if (formattedLine.length() < maxCodeLength)
splitPoint = formattedLine.length();
else
splitPoint = formattedLine.length() - 1;
if (previousNonWSChar == ']')
{
if (formattedLine.length() - 1 <= maxCodeLength)
maxWhiteSpace = splitPoint;
else
maxWhiteSpacePending = splitPoint;
}
else if (charNum > 0
&& (isLegalNameChar(currentLine[charNum - 1])
|| currentLine[charNum - 1] == ')'
|| currentLine[charNum - 1] == ']'))
{
if (formattedLine.length() <= maxCodeLength)
maxWhiteSpace = splitPoint;
else
maxWhiteSpacePending = splitPoint;
}
}
}
void ASFormatter::updateFormattedLineSplitPointsPointerOrReference(size_t index)
{
assert(maxCodeLength != string::npos);
assert(formattedLine.length() > 0);
assert(index < formattedLine.length());
if (!isOkToSplitFormattedLine())
return;
if (index < maxWhiteSpace) return;
if (index <= maxCodeLength)
maxWhiteSpace = index;
else
maxWhiteSpacePending = index;
}
bool ASFormatter::isOkToSplitFormattedLine()
{
assert(maxCodeLength != string::npos);
if (shouldKeepLineUnbroken
|| isInLineComment
|| isInComment
|| isInQuote
|| isInCase
|| isInPreprocessor
|| isInExecSQL
|| isInAsm || isInAsmOneLine || isInAsmBlock
|| isInTemplate)
return false;
if (!isOkToBreakBlock(braceTypeStack->back()) && currentChar != '{')
{
shouldKeepLineUnbroken = true;
clearFormattedLineSplitPoints();
return false;
}
if (isBraceType(braceTypeStack->back(), ARRAY_TYPE))
{
shouldKeepLineUnbroken = true;
if (!isBraceType(braceTypeStack->back(), ARRAY_NIS_TYPE))
clearFormattedLineSplitPoints();
return false;
}
return true;
}
void ASFormatter::testForTimeToSplitFormattedLine()
{
if (formattedLine.length() > maxCodeLength && !isLineReady)
{
size_t splitPoint = findFormattedLineSplitPoint();
if (splitPoint > 0 && splitPoint < formattedLine.length())
{
string splitLine = formattedLine.substr(splitPoint);
formattedLine = formattedLine.substr(0, splitPoint);
breakLine(true);
formattedLine = splitLine;
string nextWord = ASBeautifier::getNextWord(currentLine, charNum - 1);
if (isAppendPostBlockEmptyLineRequested
&& (nextWord == "break" || nextWord == "continue"))
{
isAppendPostBlockEmptyLineRequested = false;
isPrependPostBlockEmptyLineRequested = true;
}
else
isPrependPostBlockEmptyLineRequested = false;
maxAndOr = (maxAndOr > splitPoint) ? (maxAndOr - splitPoint) : 0;
maxSemi = (maxSemi > splitPoint) ? (maxSemi - splitPoint) : 0;
maxComma = (maxComma > splitPoint) ? (maxComma - splitPoint) : 0;
maxParen = (maxParen > splitPoint) ? (maxParen - splitPoint) : 0;
maxWhiteSpace = (maxWhiteSpace > splitPoint) ? (maxWhiteSpace - splitPoint) : 0;
if (maxSemiPending > 0)
{
maxSemi = (maxSemiPending > splitPoint) ? (maxSemiPending - splitPoint) : 0;
maxSemiPending = 0;
}
if (maxAndOrPending > 0)
{
maxAndOr = (maxAndOrPending > splitPoint) ? (maxAndOrPending - splitPoint) : 0;
maxAndOrPending = 0;
}
if (maxCommaPending > 0)
{
maxComma = (maxCommaPending > splitPoint) ? (maxCommaPending - splitPoint) : 0;
maxCommaPending = 0;
}
if (maxParenPending > 0)
{
maxParen = (maxParenPending > splitPoint) ? (maxParenPending - splitPoint) : 0;
maxParenPending = 0;
}
if (maxWhiteSpacePending > 0)
{
maxWhiteSpace = (maxWhiteSpacePending > splitPoint) ? (maxWhiteSpacePending - splitPoint) : 0;
maxWhiteSpacePending = 0;
}
size_t firstText = formattedLine.find_first_not_of(" \t");
if (firstText == string::npos && formattedLine.length() > 0)
{
formattedLine.erase();
clearFormattedLineSplitPoints();
if (isWhiteSpace(currentChar))
for (size_t i = charNum + 1; i < currentLine.length() && isWhiteSpace(currentLine[i]); i++)
goForward(1);
}
else if (firstText > 0)
{
formattedLine.erase(0, firstText);
maxSemi = (maxSemi > firstText) ? (maxSemi - firstText) : 0;
maxAndOr = (maxAndOr > firstText) ? (maxAndOr - firstText) : 0;
maxComma = (maxComma > firstText) ? (maxComma - firstText) : 0;
maxParen = (maxParen > firstText) ? (maxParen - firstText) : 0;
maxWhiteSpace = (maxWhiteSpace > firstText) ? (maxWhiteSpace - firstText) : 0;
}
if (formattedLineCommentNum != string::npos)
{
formattedLineCommentNum = formattedLine.find("//");
if (formattedLineCommentNum == string::npos)
formattedLineCommentNum = formattedLine.find("/*");
}
}
}
}
size_t ASFormatter::findFormattedLineSplitPoint() const
{
assert(maxCodeLength != string::npos);
size_t minCodeLength = 10;
size_t splitPoint = 0;
splitPoint = maxSemi;
if (maxAndOr >= minCodeLength)
splitPoint = maxAndOr;
if (splitPoint < minCodeLength)
{
splitPoint = maxWhiteSpace;
if (maxParen > splitPoint
|| maxParen >= maxCodeLength * .7)
splitPoint = maxParen;
if (maxComma > splitPoint
|| maxComma >= maxCodeLength * .3)
splitPoint = maxComma;
}
if (splitPoint < minCodeLength)
{
splitPoint = string::npos;
if (maxSemiPending > 0 && maxSemiPending < splitPoint)
splitPoint = maxSemiPending;
if (maxAndOrPending > 0 && maxAndOrPending < splitPoint)
splitPoint = maxAndOrPending;
if (maxCommaPending > 0 && maxCommaPending < splitPoint)
splitPoint = maxCommaPending;
if (maxParenPending > 0 && maxParenPending < splitPoint)
splitPoint = maxParenPending;
if (maxWhiteSpacePending > 0 && maxWhiteSpacePending < splitPoint)
splitPoint = maxWhiteSpacePending;
if (splitPoint == string::npos)
splitPoint = 0;
}
else if (formattedLine.length() - splitPoint > maxCodeLength)
{
size_t newCharNum;
if (isCharPotentialHeader(currentLine, charNum))
newCharNum = getCurrentWord(currentLine, charNum).length() + charNum;
else
newCharNum = charNum + 2;
if (newCharNum + 1 > currentLine.length())
{
if (maxWhiteSpace > splitPoint + 3)
splitPoint = maxWhiteSpace;
if (maxParen > splitPoint)
splitPoint = maxParen;
}
}
return splitPoint;
}
void ASFormatter::clearFormattedLineSplitPoints()
{
maxSemi = 0;
maxAndOr = 0;
maxComma = 0;
maxParen = 0;
maxWhiteSpace = 0;
maxSemiPending = 0;
maxAndOrPending = 0;
maxCommaPending = 0;
maxParenPending = 0;
maxWhiteSpacePending = 0;
}
bool ASFormatter::pointerSymbolFollows() const
{
size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
if (peekNum == string::npos || currentLine.compare(peekNum, 2, "->") != 0)
return false;
return true;
}
bool ASFormatter::computeChecksumIn(const string& currentLine_)
{
for (size_t i = 0; i < currentLine_.length(); i++)
if (!isWhiteSpace(currentLine_[i]))
checksumIn += currentLine_[i];
return true;
}
bool ASFormatter::adjustChecksumIn(int adjustment)
{
checksumIn += adjustment;
return true;
}
size_t ASFormatter::getChecksumIn() const
{
return checksumIn;
}
bool ASFormatter::computeChecksumOut(const string& beautifiedLine)
{
for (size_t i = 0; i < beautifiedLine.length(); i++)
if (!isWhiteSpace(beautifiedLine[i]))
checksumOut += beautifiedLine[i];
return true;
}
bool ASFormatter::getIsLineReady() const
{
return isLineReady;
}
size_t ASFormatter::getChecksumOut() const
{
return checksumOut;
}
int ASFormatter::getChecksumDiff() const
{
return checksumOut - checksumIn;
}
int ASFormatter::getFormatterFileType() const
{
return formatterFileType;
}
const string* ASFormatter::getFollowingOperator() const
{
size_t nextNum = currentLine.find_first_not_of(" \t", charNum + 1);
if (nextNum == string::npos)
return nullptr;
if (!isLegalNameChar(currentLine[nextNum]))
return nullptr;
while (nextNum < currentLine.length())
{
if (!isLegalNameChar(currentLine[nextNum])
&& !isWhiteSpace(currentLine[nextNum]))
break;
nextNum++;
}
if (nextNum >= currentLine.length()
|| !isCharPotentialOperator(currentLine[nextNum])
|| currentLine[nextNum] == '/') return nullptr;
const string* newOperator = ASBase::findOperator(currentLine, nextNum, operators);
return newOperator;
}
bool ASFormatter::isArrayOperator() const
{
assert(currentChar == '*' || currentChar == '&' || currentChar == '^');
assert(isBraceType(braceTypeStack->back(), ARRAY_TYPE));
size_t nextNum = currentLine.find_first_not_of(" \t", charNum + 1);
if (nextNum == string::npos)
return false;
if (!isLegalNameChar(currentLine[nextNum]))
return false;
while (nextNum < currentLine.length())
{
if (!isLegalNameChar(currentLine[nextNum])
&& !isWhiteSpace(currentLine[nextNum]))
break;
nextNum++;
}
if (currentLine[nextNum] == ','
|| currentLine[nextNum] == '}'
|| currentLine[nextNum] == ')'
|| currentLine[nextNum] == '(')
return true;
return false;
}
void ASFormatter::resetEndOfStatement()
{
foundQuestionMark = false;
foundNamespaceHeader = false;
foundClassHeader = false;
foundStructHeader = false;
foundInterfaceHeader = false;
foundPreDefinitionHeader = false;
foundPreCommandHeader = false;
foundPreCommandMacro = false;
foundTrailingReturnType = false;
foundCastOperator = false;
isInPotentialCalculation = false;
isSharpAccessor = false;
isSharpDelegate = false;
isInObjCMethodDefinition = false;
isInObjCInterface = false;
isInObjCSelector = false;
isInEnum = false;
isInExternC = false;
elseHeaderFollowsComments = false;
nonInStatementBrace = 0;
while (!questionMarkStack->empty())
questionMarkStack->pop_back();
}
int ASFormatter::findObjCColonAlignment() const
{
assert(currentChar == '+' || currentChar == '-' || currentChar == '[');
assert(getAlignMethodColon());
bool isFirstLine = true;
bool haveFirstColon = false;
bool foundMethodColon = false;
bool isInComment_ = false;
bool isInQuote_ = false;
char quoteChar_ = ' ';
int sqBracketCount = 0;
int colonAdjust = 0;
int colonAlign = 0;
string nextLine_ = currentLine;
ASPeekStream stream(sourceIterator);
while (sourceIterator->hasMoreLines() || isFirstLine)
{
if (!isFirstLine)
nextLine_ = stream.peekNextLine();
haveFirstColon = false;
nextLine_ = ASBeautifier::trim(nextLine_);
for (size_t i = 0; i < nextLine_.length(); i++)
{
if (isWhiteSpace(nextLine_[i]))
continue;
if (nextLine_.compare(i, 2, "/*") == 0)
isInComment_ = true;
if (isInComment_)
{
if (nextLine_.compare(i, 2, "*/") == 0)
{
isInComment_ = false;
++i;
}
continue;
}
if (nextLine_[i] == '\\')
{
++i;
continue;
}
if (isInQuote_)
{
if (nextLine_[i] == quoteChar_)
isInQuote_ = false;
continue;
}
if (nextLine_[i] == '"'
|| (nextLine_[i] == '\'' && !isDigitSeparator(nextLine_, i)))
{
isInQuote_ = true;
quoteChar_ = nextLine_[i];
continue;
}
if (nextLine_.compare(i, 2, "//") == 0)
{
i = nextLine_.length();
continue;
}
if ((nextLine_[i] == '{' && (currentChar == '-' || currentChar == '+'))
|| nextLine_[i] == ';')
goto EndOfWhileLoop; if (nextLine_[i] == ']')
{
--sqBracketCount;
if (sqBracketCount == 0)
goto EndOfWhileLoop; }
if (nextLine_[i] == '[')
++sqBracketCount;
if (isFirstLine) continue;
if (sqBracketCount > 1)
continue;
if (haveFirstColon) continue;
if (nextLine_[i] == ':')
{
haveFirstColon = true;
foundMethodColon = true;
if (shouldPadMethodColon)
{
int spacesStart;
for (spacesStart = i; spacesStart > 0; spacesStart--)
if (!isWhiteSpace(nextLine_[spacesStart - 1]))
break;
int spaces = i - spacesStart;
if (objCColonPadMode == COLON_PAD_ALL || objCColonPadMode == COLON_PAD_BEFORE)
colonAdjust = 1 - spaces;
else if (objCColonPadMode == COLON_PAD_NONE || objCColonPadMode == COLON_PAD_AFTER)
colonAdjust = 0 - spaces;
}
int colonPosition = i + colonAdjust;
if (colonPosition > colonAlign)
colonAlign = colonPosition;
}
} isFirstLine = false;
} EndOfWhileLoop:
if (!foundMethodColon)
colonAlign = -1;
return colonAlign;
}
void ASFormatter::padObjCMethodColon()
{
assert(currentChar == ':');
int commentAdjust = 0;
char nextChar = peekNextChar();
if (objCColonPadMode == COLON_PAD_NONE
|| objCColonPadMode == COLON_PAD_AFTER
|| nextChar == ')')
{
for (int i = formattedLine.length() - 1; (i > -1) && isWhiteSpace(formattedLine[i]); i--)
{
formattedLine.erase(i);
--commentAdjust;
}
}
else
{
for (int i = formattedLine.length() - 1; (i > 0) && isWhiteSpace(formattedLine[i]); i--)
if (isWhiteSpace(formattedLine[i - 1]))
{
formattedLine.erase(i);
--commentAdjust;
}
appendSpacePad();
}
if (objCColonPadMode == COLON_PAD_NONE
|| objCColonPadMode == COLON_PAD_BEFORE
|| nextChar == ')')
{
int nextText = currentLine.find_first_not_of(" \t", charNum + 1);
if (nextText == (int)string::npos)
nextText = currentLine.length();
int spaces = nextText - charNum - 1;
if (spaces > 0)
{
currentLine.erase(charNum + 1, spaces);
spacePadNum -= spaces;
}
}
else
{
int nextText = currentLine.find_first_not_of(" \t", charNum + 1);
if (nextText == (int)string::npos)
nextText = currentLine.length();
int spaces = nextText - charNum - 1;
if (spaces == 0)
{
currentLine.insert(charNum + 1, 1, ' ');
spacePadNum += 1;
}
else if (spaces > 1)
{
currentLine.erase(charNum + 1, spaces - 1);
spacePadNum -= spaces - 1;
}
}
spacePadNum += commentAdjust;
}
void ASFormatter::stripCommentPrefix()
{
int firstChar = formattedLine.find_first_not_of(" \t");
if (firstChar < 0)
return;
if (isInCommentStartLine)
{
if (formattedLine.compare(firstChar, 2, "/*") != 0)
return;
int commentOpener = firstChar;
int commentEnd = formattedLine.find("*/", firstChar + 2);
if (commentEnd != -1)
return;
int followingText = formattedLine.find_first_not_of(" \t", commentOpener + 2);
if (followingText < 0)
return;
if (formattedLine[followingText] == '*' || formattedLine[followingText] == '!')
followingText = formattedLine.find_first_not_of(" \t", followingText + 1);
if (followingText < 0)
return;
if (formattedLine[followingText] == '*')
return;
int indentLen = getIndentLength();
int followingTextIndent = followingText - commentOpener;
if (followingTextIndent < indentLen)
{
string stringToInsert(indentLen - followingTextIndent, ' ');
formattedLine.insert(followingText, stringToInsert);
}
return;
}
if (formattedLine[firstChar] == '*')
{
if (formattedLine.compare(firstChar, 2, "*/") == 0)
{
formattedLine = "*/";
}
else
{
int secondChar = formattedLine.find_first_not_of(" \t", firstChar + 1);
if (secondChar < 0)
{
adjustChecksumIn(-'*');
formattedLine.erase();
return;
}
if (formattedLine[secondChar] == '*')
return;
int indentLen = getIndentLength();
adjustChecksumIn(-'*');
if (formattedLine.substr(0, secondChar).find('\t') != string::npos)
{
formattedLine.erase(firstChar, 1);
}
else
{
int spacesToInsert = 0;
if (secondChar >= indentLen)
spacesToInsert = secondChar;
else
spacesToInsert = indentLen;
formattedLine = string(spacesToInsert, ' ') + formattedLine.substr(secondChar);
}
int lastChar = formattedLine.find_last_not_of(" \t");
if (lastChar > -1 && formattedLine[lastChar] == '*')
{
adjustChecksumIn(-'*');
formattedLine[lastChar] = ' ';
}
}
}
else
{
if (formattedLine.substr(0, firstChar).find('\t') == string::npos)
{
int indentLen = getIndentLength();
if (firstChar < indentLen)
{
string stringToInsert(indentLen, ' ');
formattedLine = stringToInsert + formattedLine.substr(firstChar);
}
}
}
}
}