1
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3
* Copyright (C) 2006-2009 by Jim Pattee <jimp03@email.com>
4
* Copyright (C) 1998-2002 by Tal Davidson
5
* <http://www.gnu.org/licenses/lgpl-3.0.html>
5
* This file is a part of "Artistic Style" - an indentation and
7
* This file is a part of Artistic Style - an indentation and
6
8
* reformatting tool for C, C++, C# and Java source files.
7
* http://astyle.sourceforge.net
9
* The "Artistic Style" project, including all files needed to
10
* compile it, is free software; you can redistribute it and/or
11
* modify it under the terms of the GNU Lesser General Public
12
* License as published by the Free Software Foundation; either
13
* version 2.1 of the License, or (at your option) any later
16
* This program is distributed in the hope that it will be useful,
9
* <http://astyle.sourceforge.net>
11
* Artistic Style is free software: you can redistribute it and/or modify
12
* it under the terms of the GNU Lesser General Public License as published
13
* by the Free Software Foundation, either version 3 of the License, or
14
* (at your option) any later version.
16
* Artistic Style is distributed in the hope that it will be useful,
17
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
19
* GNU Lesser General Public License for more details.
21
* You should have received a copy of the GNU Lesser General Public
22
* License along with this project; if not, write to the
23
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24
* Boston, MA 02110-1301, USA.
21
* You should have received a copy of the GNU Lesser General Public License
22
* along with Artistic Style. If not, see <http://www.gnu.org/licenses/>.
26
24
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
158
158
sourceIterator = other.sourceIterator;
160
160
// protected variables
161
fileType = other.fileType;
162
isCStyle = other.isCStyle;
163
isJavaStyle = other.isJavaStyle;
164
isSharpStyle = other.isSharpStyle;
166
161
// variables set by ASFormatter
167
// must also be updated in preprocessor
162
// must also be updated in activeBeautifierStack
168
163
inLineNumber = other.inLineNumber;
169
outLineNumber = other.outLineNumber;
164
horstmannIndentInStatement = other.horstmannIndentInStatement;
165
nonInStatementBracket = other.nonInStatementBracket;
170
166
lineCommentNoBeautify = other.lineCommentNoBeautify;
171
167
isNonInStatementArray = other.isNonInStatementArray;
168
isSharpAccessor = other.isSharpAccessor;
169
isSharpDelegate = other.isSharpDelegate;
170
isInExtern = other.isInExtern;
171
isInEnum = other.isInEnum;
173
173
// private variables
174
174
indentString = other.indentString;
175
175
currentHeader = other.currentHeader;
176
176
previousLastLineHeader = other.previousLastLineHeader;
177
immediatelyPreviousAssignmentOp = other.immediatelyPreviousAssignmentOp;
178
177
probationHeader = other.probationHeader;
179
178
isInQuote = other.isInQuote;
179
isInVerbatimQuote = other.isInVerbatimQuote;
180
haveLineContinuationChar = other.haveLineContinuationChar;
180
181
isInComment = other.isInComment;
181
182
isInCase = other.isInCase;
182
183
isInQuestion = other.isInQuestion;
183
184
isInStatement = other.isInStatement;
184
185
isInHeader = other.isInHeader;
185
isInOperator = other.isInOperator;
186
186
isInTemplate = other.isInTemplate;
187
187
isInDefine = other.isInDefine;
188
188
isInDefineDefinition = other.isInDefineDefinition;
200
200
isMinimalConditinalIndentSet = other.isMinimalConditinalIndentSet;
201
201
shouldForceTabIndentation = other.shouldForceTabIndentation;
202
202
emptyLineFill = other.emptyLineFill;
203
lineOpensComment = other.lineOpensComment;
203
204
backslashEndsPrevLine = other.backslashEndsPrevLine;
204
205
blockCommentNoIndent = other.blockCommentNoIndent;
205
206
blockCommentNoBeautify = other.blockCommentNoBeautify;
206
207
previousLineProbationTab = other.previousLineProbationTab;
208
fileType = other.fileType;
207
209
minConditionalIndent = other.minConditionalIndent;
208
210
parenDepth = other.parenDepth;
209
211
indentLength = other.indentLength;
210
212
blockTabCount = other.blockTabCount;
211
leadingWhiteSpaces = other.leadingWhiteSpaces;
212
213
maxInStatementIndent = other.maxInStatementIndent;
214
classInitializerTabs = other.classInitializerTabs;
213
215
templateDepth = other.templateDepth;
214
216
prevFinalLineSpaceTabCount = other.prevFinalLineSpaceTabCount;
215
217
prevFinalLineTabCount = other.prevFinalLineTabCount;
227
229
ASBeautifier::~ASBeautifier()
229
DELETE_CONTAINER(headerStack);
230
DELETE_CONTAINER(tempStacks);
231
DELETE_CONTAINER(blockParenDepthStack);
232
DELETE_CONTAINER(blockStatementStack);
233
DELETE_CONTAINER(parenStatementStack);
234
DELETE_CONTAINER(bracketBlockStateStack);
235
DELETE_CONTAINER(inStatementIndentStack);
236
DELETE_CONTAINER(inStatementIndentStackSizeStack);
237
DELETE_CONTAINER(parenIndentStack);
231
deleteContainer(waitingBeautifierStack);
232
deleteContainer(activeBeautifierStack);
233
deleteContainer(waitingBeautifierStackLengthStack);
234
deleteContainer(activeBeautifierStackLengthStack);
235
deleteContainer(headerStack);
236
deleteContainer(tempStacks);
237
deleteContainer(blockParenDepthStack);
238
deleteContainer(blockStatementStack);
239
deleteContainer(parenStatementStack);
240
deleteContainer(bracketBlockStateStack);
241
deleteContainer(inStatementIndentStack);
242
deleteContainer(inStatementIndentStackSizeStack);
243
deleteContainer(parenIndentStack);
261
267
void ASBeautifier::init()
265
INIT_CONTAINER(waitingBeautifierStack, new vector<ASBeautifier*>);
266
INIT_CONTAINER(activeBeautifierStack, new vector<ASBeautifier*>);
268
INIT_CONTAINER(waitingBeautifierStackLengthStack, new vector<int>);
269
INIT_CONTAINER(activeBeautifierStackLengthStack, new vector<int>);
271
INIT_CONTAINER(headerStack, new vector<const string*>);
272
INIT_CONTAINER(tempStacks, new vector<vector<const string*>*>);
270
ASBase::init(getFileType());
272
initContainer(waitingBeautifierStack, new vector<ASBeautifier*>);
273
initContainer(activeBeautifierStack, new vector<ASBeautifier*>);
275
initContainer(waitingBeautifierStackLengthStack, new vector<int>);
276
initContainer(activeBeautifierStackLengthStack, new vector<int>);
278
initContainer(headerStack, new vector<const string*>);
280
initContainer(tempStacks, new vector<vector<const string*>*>);
273
281
tempStacks->push_back(new vector<const string*>);
275
INIT_CONTAINER(blockParenDepthStack, new vector<int>);
276
INIT_CONTAINER(blockStatementStack, new vector<bool>);
277
INIT_CONTAINER(parenStatementStack, new vector<bool>);
283
initContainer(blockParenDepthStack, new vector<int>);
284
initContainer(blockStatementStack, new vector<bool>);
285
initContainer(parenStatementStack, new vector<bool>);
279
INIT_CONTAINER(bracketBlockStateStack, new vector<bool>);
287
initContainer(bracketBlockStateStack, new vector<bool>);
280
288
bracketBlockStateStack->push_back(true);
282
INIT_CONTAINER(inStatementIndentStack, new vector<int>);
283
INIT_CONTAINER(inStatementIndentStackSizeStack, new vector<int>);
290
initContainer(inStatementIndentStack, new vector<int>);
291
initContainer(inStatementIndentStackSizeStack, new vector<int>);
284
292
inStatementIndentStackSizeStack->push_back(0);
285
INIT_CONTAINER(parenIndentStack, new vector<int>);
293
initContainer(parenIndentStack, new vector<int>);
287
immediatelyPreviousAssignmentOp = NULL;
288
295
previousLastLineHeader = NULL;
289
296
currentHeader = NULL;
291
298
isInQuote = false;
299
isInVerbatimQuote = false;
300
haveLineContinuationChar = false;
292
301
isInComment = false;
293
302
isInStatement = false;
294
303
isInCase = false;
546
* get the state of the force tab indentation option.
548
* @return state of force tab indentation.
550
bool ASBeautifier::getForceTabIndentation(void)
552
return shouldForceTabIndentation;
556
* get the state of the block indentation option.
558
* @return state of blockIndent option.
560
bool ASBeautifier::getBlockIndent(void)
566
* get the state of the bracket indentation option.
568
* @return state of bracketIndent option.
570
bool ASBeautifier::getBracketIndent(void)
572
return bracketIndent;
576
* get the state of the class indentation option. If true, blocks of
577
* the 'class' statement will be indented one additional indent.
579
* @return state of classIndent option.
581
bool ASBeautifier::getClassIndent(void)
587
* get the state of the switch indentation option. If true, blocks of
588
* the 'switch' statement will be indented one additional indent.
590
* @return state of switchIndent option.
592
bool ASBeautifier::getSwitchIndent(void)
536
598
* get the state of the case indentation option. If true, lines of 'case'
537
599
* statements will be indented one additional indent.
624
653
bool lineStartsInComment = false;
625
654
bool isInClass = false;
626
655
bool isInSwitch = false;
627
bool isImmediatelyAfterConst = false;
656
bool isInOperator = false;
628
657
bool isSpecialChar = false;
658
bool haveCaseIndent = false;
659
bool lineBeginsWithBracket = false;
660
bool closingBracketReached = false;
661
bool shouldIndentBrackettedLine = true;
662
bool previousLineProbation = (probationHeader != NULL);
663
bool isInQuoteContinuation = isInVerbatimQuote | haveLineContinuationChar;
631
string outBuffer; // the newly idented line is bufferd here
632
667
int tabCount = 0;
633
const string *lastLineHeader = NULL;
634
bool closingBracketReached = false;
635
668
int spaceTabCount = 0;
637
size_t headerStackSize = headerStack->size();
638
bool shouldIndentBrackettedLine = true;
639
669
int lineOpeningBlocksNum = 0;
640
670
int lineClosingBlocksNum = 0;
641
bool previousLineProbation = (probationHeader != NULL);
671
int tabIncrementIn = 0;
674
string outBuffer; // the newly idented line is buffered here
675
const string *lastLineHeader = NULL;
644
677
currentHeader = NULL;
645
678
lineStartsInComment = isInComment;
646
679
blockCommentNoBeautify = blockCommentNoIndent;
680
lineOpensComment = false;
647
681
previousLineProbationTab = false;
682
haveLineContinuationChar = false;
650
684
// handle and remove white spaces around the line:
651
685
// If not in comment, first find out size of white space before line,
652
686
// so that possible comments starting in the line continue in
653
687
// relation to the preliminary white-space.
656
int strlen = originalLine.length();
657
leadingWhiteSpaces = 0;
659
for (int j = 0; j < strlen && isWhiteSpace(originalLine[j]); j++)
661
if (originalLine[j] == '\t')
662
leadingWhiteSpaces += indentLength;
664
leadingWhiteSpaces++;
688
if (isInQuoteContinuation)
690
// trim a single space added by ASFormatter, otherwise leave it alone
691
if (!(originalLine.length() == 1 && originalLine[0] == ' '))
694
else if (!isInComment)
666
696
line = trim(originalLine);
697
if (line.length() > 0 && line[0] == '{')
698
lineBeginsWithBracket = true;
700
size_t j = line.find_first_not_of(" \t{");
701
if (j != string::npos && line.compare(j, 2, "/*") == 0)
702
lineOpensComment = true;
670
// convert leading tabs to spaces
671
string spaceTabs(indentLength, ' ');
672
string newLine = originalLine;
673
int strlen = newLine.length();
675
for (int j=0; j < leadingWhiteSpaces && j < strlen; j++)
677
if (newLine[j] == '\t')
679
newLine.replace(j, 1, spaceTabs);
680
strlen = newLine.length();
684
// trim the comment leaving the new leading whitespace
686
strlen = newLine.length();
688
while (trimSize < strlen
689
&& trimSize < leadingWhiteSpaces
690
&& isWhiteSpace(newLine[trimSize]))
694
while (trimSize < strlen && isWhiteSpace(newLine[strlen-1]))
697
line = newLine.substr(trimSize, strlen);
706
// trim the end of comment lines
698
708
size_t trimEnd = line.find_last_not_of(" \t");
699
if (trimEnd != string::npos)
701
int spacesToDelete = line.length() - 1 - trimEnd;
702
if (spacesToDelete > 0)
703
line.erase(trimEnd + 1, spacesToDelete);
709
if (trimEnd == string::npos)
713
if (trimEnd < line.length())
708
717
if (line.length() == 0)
710
if (backslashEndsPrevLine) // must continue to clear variables
719
if (backslashEndsPrevLine) // must continue to clear variables
712
else if (emptyLineFill)
721
else if (emptyLineFill && !isInQuoteContinuation && headerStack->size() > 0)
713
722
return preLineWS(prevFinalLineSpaceTabCount, prevFinalLineTabCount);
718
727
// handle preprocessor commands
728
// except C# region and endregion
720
if (isCStyle && !isInComment && (line[0] == '#' || backslashEndsPrevLine))
731
&& (line[0] == '#' || backslashEndsPrevLine)
732
&& line.compare(0, 7, "#region") != 0
733
&& line.compare(0, 10, "#endregion") != 0)
722
735
if (line[0] == '#')
839
852
if (!isInDefine && activeBeautifierStack != NULL && !activeBeautifierStack->empty())
841
854
activeBeautifierStack->back()->inLineNumber = inLineNumber;
842
activeBeautifierStack->back()->outLineNumber = outLineNumber;
855
activeBeautifierStack->back()->horstmannIndentInStatement = horstmannIndentInStatement;
856
activeBeautifierStack->back()->nonInStatementBracket = nonInStatementBracket;
843
857
activeBeautifierStack->back()->lineCommentNoBeautify = lineCommentNoBeautify;
844
858
activeBeautifierStack->back()->isNonInStatementArray = isNonInStatementArray;
845
return activeBeautifierStack->back()->beautify(line);
859
activeBeautifierStack->back()->isSharpAccessor = isSharpAccessor;
860
activeBeautifierStack->back()->isSharpDelegate = isSharpDelegate;
861
// must return originalLine not the trimmed line
862
return activeBeautifierStack->back()->beautify(originalLine);
848
865
// calculate preliminary indentation based on data from past lines
849
866
if (!inStatementIndentStack->empty())
850
867
spaceTabCount = inStatementIndentStack->back();
853
for (i = 0; i < (int) headerStackSize; i++)
869
for (i = 0; i < (int) headerStack->size(); i++)
855
871
isInClass = false;
857
if (blockIndent || (!(i > 0 && (*headerStack)[i-1] != &AS_OPEN_BRACKET
858
&& (*headerStack)[i] == &AS_OPEN_BRACKET)))
875
// do NOT indent opening block for these headers
876
if (!((*headerStack)[i] == &AS_NAMESPACE
877
|| (*headerStack)[i] == &AS_CLASS
878
|| (*headerStack)[i] == &AS_STRUCT
879
|| (*headerStack)[i] == &AS_UNION
880
|| (*headerStack)[i] == &AS_CONST
881
|| (*headerStack)[i] == &AS_INTERFACE
882
|| (*headerStack)[i] == &AS_THROWS
883
|| (*headerStack)[i] == &AS_STATIC))
886
else if (!(i > 0 && (*headerStack)[i-1] != &AS_OPEN_BRACKET
887
&& (*headerStack)[i] == &AS_OPEN_BRACKET))
861
if (!isJavaStyle && !namespaceIndent && i >= 1
890
if (!isJavaStyle() && !namespaceIndent && i >= 1
862
891
&& (*headerStack)[i-1] == &AS_NAMESPACE
863
892
&& (*headerStack)[i] == &AS_OPEN_BRACKET)
866
if (isCStyle && i >= 1
895
if (isCStyle() && i >= 1
867
896
&& (*headerStack)[i-1] == &AS_CLASS
868
897
&& (*headerStack)[i] == &AS_OPEN_BRACKET)
887
917
if (!lineStartsInComment
891
&& headerStackSize >= 2
892
&& (*headerStack)[headerStackSize-2] == &AS_CLASS
893
&& (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET
921
&& headerStack->size() >= 2
922
&& (*headerStack)[headerStack->size()-2] == &AS_CLASS
923
&& (*headerStack)[headerStack->size()-1] == &AS_OPEN_BRACKET
925
&& bracketBlockStateStack->back() == true)
897
928
else if (!lineStartsInComment
900
&& headerStackSize >= 2
901
&& (*headerStack)[headerStackSize-2] == &AS_SWITCH
902
&& (*headerStack)[headerStackSize-1] == &AS_OPEN_BRACKET
931
&& headerStack->size() >= 2
932
&& (*headerStack)[headerStack->size()-2] == &AS_SWITCH
933
&& (*headerStack)[headerStack->size()-1] == &AS_OPEN_BRACKET
903
934
&& line[0] == '}')
906
937
if (isInClassHeader)
908
isInClassHeaderTab = true;
939
if (lineStartsInComment || lineOpensComment)
941
if (!lineBeginsWithBracket)
944
else if (isCStyle() && !isClassAccessModifier(line))
946
isInClassHeaderTab = true;
947
tabCount += classInitializerTabs;
949
else if (blockIndent)
951
if (!lineBeginsWithBracket)
912
956
if (isInConditional)
920
964
for (i = 0; i < (int) line.length(); i++)
966
outBuffer.append(1, line[i]);
922
968
tempCh = line[i];
927
outBuffer.append(1, ch);
929
972
if (isWhiteSpace(ch))
932
// check for utf8 characters
933
// isalnum() will display an assert message in debug if not bypassed here
975
tabIncrementIn += convertTabToSpaces(i, tabIncrementIn);
937
979
// handle special characters (i.e. backslash+character such as \n, \t, ...)
940
isSpecialChar = false;
943
if (!(isInComment || isInLineComment) && line.compare(i, 2, "\\\\") == 0)
945
outBuffer.append(1, '\\');
949
if (!(isInComment || isInLineComment) && ch == '\\')
951
isSpecialChar = true;
981
if (isInQuote && !isInVerbatimQuote)
985
isSpecialChar = false;
988
if (line.compare(i, 2, "\\\\") == 0)
990
outBuffer.append(1, '\\');
996
if (peekNextChar(line, i) == ' ') // is this '\' at end of line
997
haveLineContinuationChar = true;
999
isSpecialChar = true;
1003
else if (isInDefine && ch == '\\')
955
1006
// handle quotes (such as 'x' and "Hello Dolly")
956
1007
if (!(isInComment || isInLineComment) && (ch == '"' || ch == '\''))
960
1012
isInQuote = true;
1013
if (isSharpStyle() && prevCh == '@')
1014
isInVerbatimQuote = true;
1016
else if (isInVerbatimQuote && ch == '"')
1018
if (peekNextChar(line, i) == '"') // check consecutive quotes
1020
outBuffer.append(1, '"');
1026
isInVerbatimQuote = false;
962
1029
else if (quoteChar == ch)
1082
1182
inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
1084
1184
if (currentHeader != NULL)
1085
registerInStatementIndent(line, i, spaceTabCount, minConditionalIndent/*indentLength*2*/, true);
1185
registerInStatementIndent(line, i, spaceTabCount, tabIncrementIn, minConditionalIndent/*indentLength*2*/, true);
1087
registerInStatementIndent(line, i, spaceTabCount, 0, true);
1187
registerInStatementIndent(line, i, spaceTabCount, tabIncrementIn, 0, true);
1089
1189
else if (ch == ')' || ch == ']')
1092
1192
if (parenDepth == 0)
1094
isInStatement = parenStatementStack->back();
1095
parenStatementStack->pop_back();
1194
if (!parenStatementStack->empty()) // in case of unmatched closing parens
1196
isInStatement = parenStatementStack->back();
1197
parenStatementStack->pop_back();
1098
1200
isInConditional = false;
1163
1279
// this bracket is a block opener...
1165
1281
++lineOpeningBlocksNum;
1166
// if (isInClassHeader)
1167
// isInClassHeader = false;
1169
1283
if (isInClassHeaderTab)
1171
1285
isInClassHeaderTab = false;
1172
1286
// decrease tab count if bracket is broken
1173
1287
size_t firstChar = line.find_first_not_of(" \t");
1174
if (firstChar != string::npos)
1175
if (line[firstChar] == '{' && (int) firstChar == i)
1288
if (firstChar != string::npos
1289
&& line[firstChar] == '{'
1290
&& (int) firstChar == i)
1292
tabCount -= classInitializerTabs;
1293
// decrease one more if an empty class
1294
if (headerStack->size() > 0
1295
&& (*headerStack).back() == &AS_CLASS)
1297
int nextChar = getNextProgramCharDistance(line, i);
1298
if (line[nextChar] == '}')
1304
if (bracketIndent && !namespaceIndent && headerStack->size() > 0
1305
&& (*headerStack).back() == &AS_NAMESPACE)
1307
shouldIndentBrackettedLine = false;
1179
1311
// do not allow inStatementIndent - should occur for Java files only
1180
if (inStatementIndentStack->size() > 0)
1183
inStatementIndentStack->back() = 0;
1312
//if (inStatementIndentStack->size() > 0)
1314
// spaceTabCount = 0;
1315
// inStatementIndentStack->back() = 0;
1186
1318
blockParenDepthStack->push_back(parenDepth);
1187
1319
blockStatementStack->push_back(isInStatement);
1189
1321
inStatementIndentStackSizeStack->push_back(inStatementIndentStack->size());
1190
1322
if (inStatementIndentStack->size() > 0)
1191
1325
inStatementIndentStack->back() = 0;
1193
1328
blockTabCount += isInStatement ? 1 : 0;
1194
1329
parenDepth = 0;
1204
1339
//check if a header has been reached
1205
if (isWhiteSpace(prevCh))
1340
bool isPotentialHeader = isCharPotentialHeader(line, i);
1342
if (isPotentialHeader)
1207
bool isIndentableHeader = true;
1208
1344
const string *newHeader = findHeader(line, i, headers);
1346
if (newHeader != NULL)
1348
char peekChar = peekNextChar(line, i + newHeader->length() - 1);
1350
// is not a header if part of a definition
1351
if (peekChar == ',' || peekChar == ')')
1353
// the following accessor definitions are NOT headers
1354
// goto default; is NOT a header
1355
// default(int) keyword in C# is NOT a header
1356
else if ((newHeader == &AS_GET || newHeader == &AS_SET || newHeader == &AS_DEFAULT)
1357
&& (peekChar == ';' || peekChar == '('))
1209
1363
if (newHeader != NULL)
1211
1365
// if we reached here, then this is a header...
1366
bool isIndentableHeader = true;
1212
1368
isInHeader = true;
1214
1370
vector<const string*> *lastTempStack;
1558
// check for preBlockStatements ONLY if not within parenthesies
1559
// (otherwise 'struct XXX' statements would be wrongly interpreted...)
1560
if (isWhiteSpace(prevCh) && !isInTemplate && parenDepth == 0)
1704
if (isPotentialHeader)
1562
const string *newHeader = findHeader(line, i, preBlockStatements);
1563
if (newHeader != NULL)
1565
isInClassHeader = true;
1566
outBuffer.append(newHeader->substr(1));
1567
i += newHeader->length() - 1;
1568
headerStack->push_back(newHeader);
1706
// check for preBlockStatements in C/C++ ONLY if not within parenthesies
1707
// (otherwise 'struct XXX' statements would be wrongly interpreted...)
1708
if (!isInTemplate && !(isCStyle() && parenDepth > 0))
1710
const string *newHeader = findHeader(line, i, preBlockStatements);
1711
if (newHeader != NULL)
1713
isInClassHeader = true;
1715
if (!isSharpStyle())
1716
headerStack->push_back(newHeader);
1717
// do not need 'where' in the headerStack
1718
// do not need second 'class' statement in a row
1719
else if (!(newHeader == &AS_WHERE
1720
|| (newHeader == &AS_CLASS
1721
&& headerStack->size() > 0
1722
&& headerStack->back() == &AS_CLASS)))
1723
headerStack->push_back(newHeader);
1725
outBuffer.append(newHeader->substr(1));
1726
i += newHeader->length() - 1;
1730
const string *foundIndentableHeader = findHeader(line, i, indentableHeaders);
1732
if (foundIndentableHeader != NULL)
1734
// must bypass the header before registering the in statement
1735
outBuffer.append(foundIndentableHeader->substr(1));
1736
i += foundIndentableHeader->length() - 1;
1737
if (!isInOperator && !isInTemplate && !isNonInStatementArray)
1739
registerInStatementIndent(line, i, spaceTabCount, tabIncrementIn, 0, false);
1740
isInStatement = true;
1745
if (isCStyle() && findKeyword(line, i, AS_OPERATOR))
1746
isInOperator = true;
1748
// "new" operator is a pointer, not a calculation
1749
if (findKeyword(line, i, AS_NEW))
1751
if (prevNonSpaceCh == '=' && isInStatement && !inStatementIndentStack->empty())
1752
inStatementIndentStack->back() = 0;
1755
// append the entire name for all others
1756
string name = getCurrentWord(line, i);
1757
outBuffer.append(name.substr(1));
1758
i += name.length() - 1;
1572
1762
// Handle operators
1574
immediatelyPreviousAssignmentOp = NULL;
1576
// Check if an operator has been reached.
1577
const string *foundAssignmentOp = findHeader(line, i, assignmentOperators, false);
1578
if (foundAssignmentOp == &AS_RETURN)
1579
foundAssignmentOp = findHeader(line, i, assignmentOperators, true);
1580
const string *foundNonAssignmentOp = findHeader(line, i, nonAssignmentOperators, false);
1582
// Since findHeader's boundry checking was not used above, it is possible
1583
// that both an assignment op and a non-assignment op where found,
1584
// e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the
1586
if (foundAssignmentOp != NULL && foundNonAssignmentOp != NULL)
1587
if (foundAssignmentOp->length() < foundNonAssignmentOp->length())
1588
foundAssignmentOp = NULL;
1590
foundNonAssignmentOp = NULL;
1592
if (foundNonAssignmentOp != NULL)
1594
if (foundNonAssignmentOp->length() > 1)
1596
outBuffer.append(foundNonAssignmentOp->substr(1));
1597
i += foundNonAssignmentOp->length() - 1;
1601
else if (foundAssignmentOp != NULL)
1603
if (foundAssignmentOp->length() > 1)
1605
outBuffer.append(foundAssignmentOp->substr(1));
1606
i += foundAssignmentOp->length() - 1;
1609
if (!isInOperator && !isInTemplate && !isNonInStatementArray)
1611
registerInStatementIndent(line, i, spaceTabCount, 0, false);
1612
immediatelyPreviousAssignmentOp = foundAssignmentOp;
1613
isInStatement = true;
1618
isInOperator = false;
1764
bool isPotentialOperator = isCharPotentialOperator(ch);
1766
if (isPotentialOperator)
1768
// Check if an operator has been reached.
1769
const string *foundAssignmentOp = findOperator(line, i, assignmentOperators);
1770
const string *foundNonAssignmentOp = findOperator(line, i, nonAssignmentOperators);
1772
// Since findHeader's boundry checking was not used above, it is possible
1773
// that both an assignment op and a non-assignment op where found,
1774
// e.g. '>>' and '>>='. If this is the case, treat the LONGER one as the
1776
if (foundAssignmentOp != NULL && foundNonAssignmentOp != NULL)
1778
if (foundAssignmentOp->length() < foundNonAssignmentOp->length())
1779
foundAssignmentOp = NULL;
1781
foundNonAssignmentOp = NULL;
1784
if (foundNonAssignmentOp != NULL)
1786
if (foundNonAssignmentOp->length() > 1)
1788
outBuffer.append(foundNonAssignmentOp->substr(1));
1789
i += foundNonAssignmentOp->length() - 1;
1793
else if (foundAssignmentOp != NULL)
1795
if (foundAssignmentOp->length() > 1)
1797
outBuffer.append(foundAssignmentOp->substr(1));
1798
i += foundAssignmentOp->length() - 1;
1801
if (!isInOperator && !isInTemplate && !isNonInStatementArray)
1803
registerInStatementIndent(line, i, spaceTabCount, tabIncrementIn, 0, false);
1804
isInStatement = true;
1808
} // end of for loop * end of for loop * end of for loop * end of for loop
1621
1810
// handle special cases of unindentation:
1937
bool ASBeautifier::isClassAccessModifier(string& line) const
1939
size_t firstChar = line.find_first_not_of(" \t");
1940
if (firstChar == string::npos)
1943
if (line[firstChar] == ':')
1945
firstChar = line.find_first_not_of(" \t");
1946
if (firstChar == string::npos)
1949
if (line.compare(firstChar, 7, "public ") == 0
1950
|| line.compare(firstChar, 8, "private ") == 0
1951
|| line.compare(firstChar, 10, "protected ") == 0)
1724
1957
* register an in-statement indent.
1726
1959
void ASBeautifier::registerInStatementIndent(const string &line, int i, int spaceTabCount,
1727
int minIndent, bool updateParenStack)
1960
int tabIncrementIn, int minIndent, bool updateParenStack)
1729
1962
int inStatementIndent;
1730
1963
int remainingCharNum = line.length() - i;
1731
1964
int nextNonWSChar = getNextProgramCharDistance(line, i);
1733
// if indent is around the last char in the line, indent instead 2 spaces from the previous indent
1966
// if indent is around the last char in the line, indent instead one indent from the previous indent
1734
1967
if (nextNonWSChar == remainingCharNum)
1736
1969
int previousIndent = spaceTabCount;
1737
1970
if (!inStatementIndentStack->empty())
1738
1971
previousIndent = inStatementIndentStack->back();
1740
inStatementIndentStack->push_back(/*2*/ indentLength + previousIndent);
1972
int currIndent = /*2*/ indentLength + previousIndent;
1973
if (currIndent > maxInStatementIndent
1975
currIndent = indentLength * 2 + spaceTabCount;
1976
inStatementIndentStack->push_back(currIndent);
1741
1977
if (updateParenStack)
1742
1978
parenIndentStack->push_back(previousIndent);
1746
1982
if (updateParenStack)
1747
parenIndentStack->push_back(i + spaceTabCount);
1749
inStatementIndent = i + nextNonWSChar + spaceTabCount;
1751
if (i + nextNonWSChar < minIndent)
1983
parenIndentStack->push_back(i + spaceTabCount - horstmannIndentInStatement);
1985
int tabIncrement = tabIncrementIn;
1987
// check for following tabs
1988
for (int j = i + 1; j < (i + nextNonWSChar); j++)
1990
if (line[j] == '\t')
1991
tabIncrement += convertTabToSpaces(j, tabIncrement);
1994
inStatementIndent = i + nextNonWSChar + spaceTabCount + tabIncrement;
1996
// check for run-in statement
1997
if (i > 0 && line[0] == '{')
1998
inStatementIndent -= indentLength;
2000
// if (i + nextNonWSChar < minIndent)
2001
// inStatementIndent = minIndent + spaceTabCount;
2003
if (inStatementIndent < minIndent)
1752
2004
inStatementIndent = minIndent + spaceTabCount;
1754
if (i + nextNonWSChar > maxInStatementIndent)
1755
inStatementIndent = indentLength * 2 + spaceTabCount;
2006
// if (i + nextNonWSChar > maxInStatementIndent)
2007
// inStatementIndent = indentLength * 2 + spaceTabCount;
2009
if (inStatementIndent > maxInStatementIndent)
2010
inStatementIndent = indentLength * 2 + spaceTabCount;
1757
2012
if (!inStatementIndentStack->empty() &&
1758
2013
inStatementIndent < inStatementIndentStack->back())
1759
2014
inStatementIndent = inStatementIndentStack->back();
1761
if (isNonInStatementArray)
2016
// the block opener is not indented for a NonInStatementArray
2017
if (isNonInStatementArray && !bracketBlockStateStack->empty() && bracketBlockStateStack->back())
1762
2018
inStatementIndent = 0;
1764
2020
inStatementIndentStack->push_back(inStatementIndent);
1768
* get distance to the next non-white sspace, non-comment character in the line.
2024
* get distance to the next non-white space, non-comment character in the line.
1769
2025
* if no such character exists, return the length remaining to the end of the line.
1771
int ASBeautifier::getNextProgramCharDistance(const string &line, int i)
2027
int ASBeautifier::getNextProgramCharDistance(const string &line, int i) const
1773
2029
bool inComment = false;
1774
2030
int remainingCharNum = line.length() - i;
1806
2062
return charDistance;
1811
* check if a specific line position contains a header, out of several possible headers.
1813
* @return a pointer to the found header. if no header was found then return NULL.
1815
const string *ASBeautifier::findHeader(const string &line, int i, const vector<const string*> &possibleHeaders, bool checkBoundry)
1817
int maxHeaders = possibleHeaders.size();
1818
// const string *header = NULL;
1821
for (p = 0; p < maxHeaders; p++)
1823
const string *header = possibleHeaders[p];
1825
if (line.compare(i, header->length(), header->c_str()) == 0)
1827
// check that this is a header and not a part of a longer word
1828
// (e.g. not at its begining, not at its middle...)
1830
int lineLength = line.length();
1831
int headerEnd = i + header->length();
1832
char startCh = (*header)[0]; // first char of header
1833
char endCh = 0; // char just after header
1834
char prevCh = 0; // char just before header
1836
if (headerEnd < lineLength)
1838
endCh = line[headerEnd];
1849
else if (prevCh != 0
1850
&& isLegalNameChar(startCh)
1851
&& isLegalNameChar(prevCh))
1855
else if (headerEnd >= lineLength
1856
|| !isLegalNameChar(startCh)
1857
|| !isLegalNameChar(endCh))
2065
// check if a specific line position contains a header.
2066
const string* ASBeautifier::findHeader(const string &line, int i,
2067
const vector<const string*> &possibleHeaders) const
2069
assert(isCharPotentialHeader(line, i));
2071
size_t maxHeaders = possibleHeaders.size();
2072
for (size_t p = 0; p < maxHeaders; p++)
2074
const string* header = possibleHeaders[p];
2075
const size_t wordEnd = i + header->length();
2076
if (wordEnd > line.length())
2078
int result = (line.compare(i, header->length(), *header));
2083
// check that this is not part of a longer word
2084
if (wordEnd == line.length())
2086
if (isLegalNameChar(line[wordEnd]))
2088
// is not a header if part of a definition
2089
const char peekChar = peekNextChar(line, wordEnd - 1);
2090
if (peekChar == ',' || peekChar == ')')
2098
// check if a specific line position contains an operator.
2099
const string* ASBeautifier::findOperator(const string &line, int i,
2100
const vector<const string*> &possibleOperators) const
2102
assert(isCharPotentialOperator(line[i]));
2103
// find the operator in the vector
2104
// the vector contains the LONGEST operators first
2105
// must loop thru the entire vector
2106
size_t maxOperators = possibleOperators.size();
2107
for (size_t p = 0; p < maxOperators; p++)
2109
const size_t wordEnd = i + (*possibleOperators[p]).length();
2110
if (wordEnd > line.length())
2112
if (line.compare(i, (*possibleOperators[p]).length(), *possibleOperators[p]) == 0)
2113
return possibleOperators[p];
1912
* peek at the next unread character.
1914
* @return the next unread character.
1915
* @param line the line to check.
1916
* @param i the current char position on the line.
1918
char ASBeautifier::peekNextChar(string &line, int i)
1921
size_t peekNum = line.find_first_not_of(" \t", i + 1);
1923
if (peekNum == string::npos)
2171
* delete a static member vector object using swap
2172
* to eliminate memory leak reporting for the vector
2174
void ASBeautifier::deleteStaticVectors()
2176
beautifierFileType = 9; // reset to an invalid type
2177
vector<const string*> headersClear;
2178
headers.swap(headersClear);
2179
vector<const string*> nonParenHeadersClear;
2180
nonParenHeaders.swap(nonParenHeadersClear);
2181
vector<const string*> preBlockStatementsClear;
2182
preBlockStatements.swap(preBlockStatementsClear);
2183
vector<const string*> assignmentOperatorsClear;
2184
assignmentOperators.swap(assignmentOperatorsClear);
2185
vector<const string*> nonAssignmentOperatorsClear;
2186
nonAssignmentOperators.swap(nonAssignmentOperatorsClear);
2187
vector<const string*> indentableHeadersClear;
2188
indentableHeaders.swap(indentableHeadersClear);
2192
* delete a vector object
2193
* T is the type of vector
2194
* used for all vectors except tempStacks
2196
template<typename T>
2197
void ASBeautifier::deleteContainer(T &container)
2199
if (container != NULL)
2208
* Delete the tempStacks vector object.
2209
* The tempStacks is a vector of pointers to strings allocated with
2210
* the 'new' operator.
2211
* Therefore the strings have to be deleted in addition to the
2212
* tempStacks entries.
2214
void ASBeautifier::deleteContainer(vector<vector<const string*>*>* &container)
2216
if (container != NULL)
2218
vector<vector<const string*>*>::iterator iter = container->begin();
2219
for (; iter != container->end(); iter++)
2228
* initialize a vector object
2229
* T is the type of vector
2230
* used for all vectors
2232
template<typename T>
2233
void ASBeautifier::initContainer(T &container, T value)
2235
// since the ASFormatter object is never deleted,
2236
// the existing vectors must be deleted before creating new ones
2237
if (container != NULL )
2238
deleteContainer(container);