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