1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
5
* This file is a part of "Artistic Style" - an indentation and
6
* 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,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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.
26
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
35
// can trace only if NDEBUG is not defined
38
// #define TRACEcomment
39
// #define TRACEheader
40
// #define TRACEbracket
42
#if defined(TRACEunpad) || defined(TRACEcomment) || defined(TRACEheader) \
43
|| defined(TRACEbracket) || defined(TRACEarray)
50
#define TRunpad(a,b,c) if(b > 0 || c > 0) *traceOutF << traceLineNumber << " " << b << a << c << endl
52
#define TRunpad(a,b,c) ((void)0)
56
#define TRcomment(a) *traceOutF << traceLineNumber << " " << a << endl
58
#define TRcomment(a) ((void)0)
62
#define TRxtra(a) *traceOutF << traceLineNumber << " " << a << endl
64
#define TRxtra(a) ((void)0)
68
#define TRbracket(a) *traceOutF << traceLineNumber << " " << a << endl
70
#define TRbracket(a) ((void)0)
74
#define TRarray(a) *traceOutF << traceLineNumber << " " << a << endl
76
#define TRarray(a) ((void)0)
79
#define INIT_CONTAINER(container, value) {if ( (container) != NULL ) delete (container); (container) = (value); }
80
#define DELETE_CONTAINER(container) {if ( (container) != NULL ) delete (container); }
81
#define IS_A(a,b) ( ((a) & (b)) == (b))
87
vector<const string*> ASFormatter::headers;
88
vector<const string*> ASFormatter::nonParenHeaders;
89
vector<const string*> ASFormatter::preDefinitionHeaders;
90
vector<const string*> ASFormatter::preCommandHeaders;
91
vector<const string*> ASFormatter::operators;
92
vector<const string*> ASFormatter::assignmentOperators;
93
vector<const string*> ASFormatter::castOperators;
96
* Constructor of ASFormatter
98
ASFormatter::ASFormatter()
100
preBracketHeaderStack = NULL;
101
bracketTypeStack = NULL;
103
lineCommentNoIndent = false;
104
sourceIterator = NULL;
105
bracketFormatMode = NONE_MODE;
106
shouldPadOperators = false;
107
shouldPadParensOutside = false;
108
shouldPadParensInside = false;
109
shouldUnPadParens = false;
110
shouldBreakOneLineBlocks = true;
111
shouldBreakOneLineStatements = true;
112
shouldConvertTabs = false;
113
shouldBreakBlocks = false;
114
shouldBreakClosingHeaderBlocks = false;
115
shouldBreakClosingHeaderBrackets = false;
116
shouldBreakElseIfs = false;
118
// create a trace text file
119
string traceFileName = "tracef.txt";
120
char* env = getenv("HOME");
122
traceFileName = string(env) + string("/tracef.txt");
125
env = getenv("USERPROFILE");
127
traceFileName = string(env) + string("\\My Documents\\tracef.txt");
130
cout << "\nCould not open tracef.txt\n" << endl;
134
traceOutF = new ofstream(traceFileName.c_str());
139
* Destructor of ASFormatter
141
ASFormatter::~ASFormatter()
143
DELETE_CONTAINER(preBracketHeaderStack);
150
* initialization of static data of ASFormatter.
152
void ASFormatter::staticInit()
154
static int formatterFileType = 9; // initialized with an invalid type
156
if (fileType == formatterFileType) // don't build unless necessary
159
formatterFileType = fileType;
162
nonParenHeaders.clear();
163
assignmentOperators.clear();
165
preDefinitionHeaders.clear();
166
preCommandHeaders.clear();
167
castOperators.clear();
169
ASResource::buildHeaders(headers, fileType);
170
ASResource::buildNonParenHeaders(nonParenHeaders, fileType);
171
ASResource::buildAssignmentOperators(assignmentOperators);
172
ASResource::buildOperators(operators);
173
ASResource::buildPreDefinitionHeaders(preDefinitionHeaders);
174
ASResource::buildPreCommandHeaders(preCommandHeaders);
175
ASResource::buildCastOperators(castOperators);
179
* initialize the ASFormatter.
181
* init() should be called every time a ASFormatter object is to start
182
* formatting a NEW source file.
183
* init() receives a pointer to a DYNAMICALLY CREATED ASSourceIterator object
184
* that will be used to iterate through the source code. This object will be
185
* deleted during the ASFormatter's destruction, and thus should not be
188
* @param iter a pointer to the DYNAMICALLY CREATED ASSourceIterator object.
190
void ASFormatter::init(ASSourceIterator *si)
194
ASBeautifier::init(si);
195
ASEnhancer::init(getIndentLength(),
204
INIT_CONTAINER(preBracketHeaderStack, new vector<const string*>);
205
INIT_CONTAINER(bracketTypeStack, new vector<BracketType>);
206
bracketTypeStack->push_back(NULL_TYPE);
207
INIT_CONTAINER(parenStack, new vector<int>);
208
parenStack->push_back(0); // parenStack must contain this default entry
210
currentHeader = NULL;
211
currentLine = string("");
212
readyFormattedLine = string("");
216
previousCommandChar = ' ';
217
previousNonWSChar = ' ';
221
previousReadyFormattedLineLength = string::npos;
224
previousBracketType = NULL_TYPE;
225
previousOperator = NULL;
228
isInLineComment = false;
230
isInPreprocessor = false;
231
doesLineStartComment = false;
233
isInVerbatimQuote = false;
234
haveLineContinuationChar = false;
235
isInQuoteContinuation = false;
236
isSpecialChar = false;
237
isNonParenHeader = true;
238
foundNamespaceHeader = false;
239
foundClassHeader = false;
240
foundPreDefinitionHeader = false;
241
foundPreCommandHeader = false;
242
foundCastOperator = false;
243
foundQuestionMark = false;
244
isInLineBreak = false;
245
endOfCodeReached = false;
247
isPreviousBracketBlockRelated = true;
248
isInPotentialCalculation = false;
249
shouldReparseCurrentChar = false;
250
passedSemicolon = false;
252
isInTemplate = false;
254
// shouldBreakLineAfterComments = false;
255
isImmediatelyPostComment = false;
256
isImmediatelyPostLineComment = false;
257
isImmediatelyPostEmptyBlock = false;
258
isImmediatelyPostPreprocessor = false;
260
isPrependPostBlockEmptyLineRequested = false;
261
isAppendPostBlockEmptyLineRequested = false;
262
prependEmptyLine = false;
263
appendOpeningBracket = false;
265
foundClosingHeader = false;
266
previousReadyFormattedLineLength = 0;
268
isImmediatelyPostHeader = false;
272
// traceFileName will be empty if ASTYLE_LIB is defined
273
if (traceFileName.empty())
274
*traceOutF << "new file" << endl;
276
*traceOutF << traceFileName << endl;
281
* get the next formatted line.
283
* @return formatted line.
286
string ASFormatter::nextLine()
288
// these are reset with each new line
289
const string *newHeader;
290
bool isInVirginLine = isVirgin;
291
isCharImmediatelyPostComment = false;
292
isPreviousCharPostComment = false;
293
isCharImmediatelyPostLineComment = false;
294
isCharImmediatelyPostOpenBlock = false;
295
isCharImmediatelyPostCloseBlock = false;
296
isCharImmediatelyPostTemplate = false;
301
if (shouldReparseCurrentChar)
302
shouldReparseCurrentChar = false;
303
else if (!getNextChar())
306
return beautify(readyFormattedLine);
308
else // stuff to do when reading a new character...
310
// make sure that a virgin '{' at the beginning ofthe file will be treated as a block...
311
if (isInVirginLine && currentChar == '{' && lineBeginsWith('{'))
312
previousCommandChar = '{';
313
isPreviousCharPostComment = isCharImmediatelyPostComment;
314
isCharImmediatelyPostComment = false;
315
isCharImmediatelyPostTemplate = false;
318
// if (inLineNumber >= 1159)
325
// explicitly break a line when a line comment's end is found.
326
if (charNum + 1 == (int) currentLine.length())
328
isInLineBreak = true;
329
isInLineComment = false;
330
isImmediatelyPostLineComment = true;
331
currentChar = 0; //make sure it is a neutral char.
335
else if (isInComment)
337
if (isSequenceReached("*/"))
340
isImmediatelyPostComment = true;
341
appendSequence(AS_CLOSE_COMMENT);
350
// not in line comment or comment
356
isSpecialChar = false;
358
else if (currentChar == '\\' && !isInVerbatimQuote)
360
if (peekNextChar() == ' ') // is this '\' at end of line
361
haveLineContinuationChar = true;
363
isSpecialChar = true;
365
else if (isInVerbatimQuote && currentChar == '"' )
367
if (peekNextChar() == '"') // check consecutive quotes
369
appendSequence("\"\"");
376
isInVerbatimQuote = false;
379
else if (quoteChar == currentChar)
388
if (isSequenceReached("//"))
390
if (currentLine[charNum+2] == '\xf2') // check for windows line marker
391
isAppendPostBlockEmptyLineRequested = false;
392
isInLineComment = true;
393
// do not indent if in column 1 or 2
394
if (lineCommentNoIndent == false)
397
lineCommentNoIndent = true;
398
else if (charNum == 1 && currentLine[0] == ' ')
399
lineCommentNoIndent = true;
401
// move comment if spaces were added or deleted
402
if (lineCommentNoIndent == false && spacePadNum != 0)
404
formattedLineCommentNum = formattedLine.length();
405
appendSequence(AS_OPEN_LINE_COMMENT);
407
// explicitly break a line when a line comment's end is found.
408
if (charNum + 1 == (int) currentLine.length())
410
isInLineBreak = true;
411
isInLineComment = false;
412
isImmediatelyPostLineComment = true;
413
currentChar = 0; //make sure it is a neutral char.
417
else if (isSequenceReached("/*"))
420
if (spacePadNum != 0)
422
formattedLineCommentNum = formattedLine.length();
423
appendSequence(AS_OPEN_COMMENT);
427
else if (currentChar == '"' || currentChar == '\'')
430
if (isSharpStyle && previousChar == '@')
431
isInVerbatimQuote = true;
432
quoteChar = currentChar;
437
// handle white space - needed to simplify the rest.
438
if (isWhiteSpace(currentChar) || isInPreprocessor)
444
/* not in MIDDLE of quote or comment or white-space of any type ... */
446
// need to reset 'previous' chars if appending a bracket
447
if (appendOpeningBracket)
448
previousCommandChar = previousNonWSChar = previousChar = '{';
450
// check if in preprocessor
451
// ** isInPreprocessor will be automatically reset at the beginning
452
// of a new line in getnextChar()
453
if (isCStyle && currentChar == '#')
455
isInPreprocessor = true;
460
/* not in preprocessor ... */
462
if (isImmediatelyPostComment)
464
isImmediatelyPostComment = false;
465
isCharImmediatelyPostComment = true;
468
if (isImmediatelyPostLineComment)
470
isImmediatelyPostLineComment = false;
471
isCharImmediatelyPostLineComment = true;
474
// if (shouldBreakLineAfterComments)
476
// shouldBreakLineAfterComments = false;
477
// shouldReparseCurrentChar = true;
482
// reset isImmediatelyPostHeader information
483
if (isImmediatelyPostHeader)
485
isImmediatelyPostHeader = false;
487
// Make sure headers are broken from their succeeding blocks
489
// if (isFoo) DoBar();
494
// But treat else if() as a special case which should not be broken!
495
if (shouldBreakOneLineStatements)
497
// if may break 'else if()'s, then simply break the line
499
if (shouldBreakElseIfs)
500
isInLineBreak = true;
504
if (passedSemicolon) // need to break the formattedLine
506
passedSemicolon = false;
507
if (parenStack->back() == 0 && currentChar != ';') // allow ;;
509
// does a one-line statement have ending comments?
510
if (IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE))
512
size_t blockEnd = currentLine.rfind(AS_CLOSE_BRACKET);
513
assert(blockEnd != string::npos);
514
// move ending comments to this formattedLine
515
if (isBeforeLineEndComment(blockEnd))
517
size_t commentStart = currentLine.find_first_not_of(" \t", blockEnd + 1);
518
assert(commentStart != string::npos);
519
assert((currentLine.compare(commentStart, 2, "//") == 0)
520
|| (currentLine.compare(commentStart, 2, "/*") == 0));
521
size_t commentLength = currentLine.length() - commentStart;
522
int tabCount = getIndentLength();
524
for (int i=1; i<tabCount; i++)
525
formattedLine.append(1, ' ');
526
formattedLine.append(currentLine, commentStart, commentLength);
527
currentLine.erase(commentStart, commentLength);
530
shouldReparseCurrentChar = true;
531
isInLineBreak = true;
539
if (parenStack->back() == 0 && !isBeforeComment())
541
shouldReparseCurrentChar = true;
542
isInLineBreak = true;
547
// Check if in template declaration, e.g. foo<bar> or foo<bar,fig>
548
// If so, set isInTemplate to true
549
if (!isInTemplate && currentChar == '<')
551
int maxTemplateDepth = 0;
553
for (size_t i = charNum;
554
i < currentLine.length();
557
char currentChar = currentLine[i];
559
if (currentChar == '<')
564
else if (currentChar == '>')
567
if (templateDepth == 0)
569
// this is a template!
571
templateDepth = maxTemplateDepth;
575
else if (currentChar == ',' // comma, e.g. A<int, char>
576
|| currentChar == '&' // reference, e.g. A<int&>
577
|| currentChar == '*' // pointer, e.g. A<int*>
578
|| currentChar == ':' // ::, e.g. std::string
579
|| currentChar == '[' // [] e.g. string[]
580
|| currentChar == ']') // [] e.g. string[]
584
else if (!isLegalNameChar(currentChar) && !isWhiteSpace(currentChar))
586
// this is not a template -> leave...
587
isInTemplate = false;
593
// handle parenthesies
594
if (currentChar == '(' || currentChar == '[' || (isInTemplate && currentChar == '<'))
596
parenStack->back()++;
597
if (currentChar == '[')
600
else if (currentChar == ')' || currentChar == ']' || (isInTemplate && currentChar == '>'))
602
parenStack->back()--;
603
if (isInTemplate && currentChar == '>')
606
if (templateDepth == 0)
608
isInTemplate = false;
609
isCharImmediatelyPostTemplate = true;
613
// check if this parenthesis closes a header, e.g. if (...), while (...)
614
if (isInHeader && parenStack->back() == 0)
617
isImmediatelyPostHeader = true;
619
if (currentChar == ']')
621
if (currentChar == ')')
622
foundCastOperator = false;
626
if (currentChar == '{' || currentChar == '}')
628
if (currentChar == '{')
630
BracketType newBracketType = getBracketType();
631
foundNamespaceHeader = false;
632
foundClassHeader = false;
633
foundPreDefinitionHeader = false;
634
foundPreCommandHeader = false;
635
isInPotentialCalculation = false;
637
bracketTypeStack->push_back(newBracketType);
638
preBracketHeaderStack->push_back(currentHeader);
639
currentHeader = NULL;
641
isPreviousBracketBlockRelated = !IS_A(newBracketType, ARRAY_TYPE);
644
// this must be done before the bracketTypeStack is popped
645
BracketType bracketType = bracketTypeStack->back();
646
bool isOpeningArrayBracket = (IS_A(bracketType, ARRAY_TYPE)
647
&& bracketTypeStack->size() >= 2
648
&& !IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], ARRAY_TYPE)
651
if (currentChar == '}')
653
// if a request has been made to append a post block empty line,
654
// but the block exists immediately before a closing bracket,
655
// then there is not need for the post block empty line.
657
isAppendPostBlockEmptyLineRequested = false;
659
if (bracketTypeStack->size() > 1)
661
previousBracketType = bracketTypeStack->back();
662
bracketTypeStack->pop_back();
663
isPreviousBracketBlockRelated = !IS_A(bracketType, ARRAY_TYPE);
667
previousBracketType = NULL_TYPE;
668
isPreviousBracketBlockRelated = false;
671
if (!preBracketHeaderStack->empty())
673
currentHeader = preBracketHeaderStack->back();
674
preBracketHeaderStack->pop_back();
677
currentHeader = NULL;
681
if (IS_A(bracketType, ARRAY_TYPE))
682
formatArrayBrackets(bracketType, isOpeningArrayBracket);
684
formatBrackets(bracketType);
688
if (((previousCommandChar == '{' && isPreviousBracketBlockRelated)
689
|| ((previousCommandChar == '}'
690
&& bracketFormatMode != NONE_MODE
691
&& !isImmediatelyPostEmptyBlock
692
&& isPreviousBracketBlockRelated
693
&& !isPreviousCharPostComment // Fixes wrongly appended newlines after '}' immediately after comments
694
&& peekNextChar() != ' '
695
&& !IS_A(previousBracketType, DEFINITION_TYPE)
696
&& !(isJavaStyle && currentChar == ')'))
697
&& !IS_A(bracketTypeStack->back(), DEFINITION_TYPE)))
698
&& (shouldBreakOneLineBlocks
699
|| !IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE)))
701
isCharImmediatelyPostOpenBlock = (previousCommandChar == '{');
702
isCharImmediatelyPostCloseBlock = (previousCommandChar == '}');
704
previousCommandChar = ' ';
705
isInLineBreak = true;
708
// reset block handling flags
709
isImmediatelyPostEmptyBlock = false;
714
newHeader = findHeader(headers);
716
if (newHeader != NULL)
718
char peekChar = ASBeautifier::peekNextChar(currentLine, charNum + newHeader->length() - 1);
720
// is not a header if part of a definition
721
if (peekChar == ',' || peekChar == ')')
723
// the following accessor definitions are NOT headers
724
// goto default; is NOT a header
725
else if ((newHeader == &AS_GET || newHeader == &AS_SET || newHeader == &AS_DEFAULT)
732
if (newHeader != NULL)
734
foundClosingHeader = false;
735
const string *previousHeader;
737
// recognize closing headers of do..while, if..else, try..catch..finally
738
if ((newHeader == &AS_ELSE && currentHeader == &AS_IF)
739
|| (newHeader == &AS_WHILE && currentHeader == &AS_DO)
740
|| (newHeader == &AS_CATCH && currentHeader == &AS_TRY)
741
|| (newHeader == &AS_CATCH && currentHeader == &AS_CATCH)
742
|| (newHeader == &AS_FINALLY && currentHeader == &AS_TRY)
743
|| (newHeader == &AS_FINALLY && currentHeader == &AS_CATCH))
744
foundClosingHeader = true;
746
previousHeader = currentHeader;
747
currentHeader = newHeader;
749
// If in ATTACH or LINUX bracket modes, attach closing headers (e.g. 'else', 'catch')
750
// to their preceding bracket,
751
// But do not perform the attachment if the shouldBreakClosingHeaderBrackets is set!
752
if (!shouldBreakClosingHeaderBrackets
753
&& foundClosingHeader
754
&& (bracketFormatMode == ATTACH_MODE || bracketFormatMode == BDAC_MODE)
755
&& (shouldBreakOneLineBlocks || !IS_A(previousBracketType, SINGLE_LINE_TYPE))
756
&& previousNonWSChar == '}')
758
spacePadNum = 0; // don't count as padding
760
size_t firstChar = formattedLine.find_first_not_of(" \t");
761
if (firstChar != string::npos) // if a blank line does not preceed this
763
isInLineBreak = false;
767
if (shouldBreakBlocks)
768
isAppendPostBlockEmptyLineRequested = false;
771
// If NONE bracket mode, leave closing headers as they are (e.g. 'else', 'catch')
772
if (foundClosingHeader && bracketFormatMode == NONE_MODE && previousCommandChar == '}')
774
// is closing bracket broken?
775
// do NOT want to check the current char
776
size_t i = currentLine.find_first_not_of(" \t");
777
if (i != string::npos && currentLine[i] == '}')
779
isInLineBreak = false;
783
if (shouldBreakBlocks)
784
isAppendPostBlockEmptyLineRequested = false;
787
if (foundClosingHeader && bracketFormatMode == BREAK_MODE && previousCommandChar == '}')
790
// check if the found header is non-paren header
791
isNonParenHeader = (find(nonParenHeaders.begin(), nonParenHeaders.end(),
792
newHeader) != nonParenHeaders.end());
794
appendSequence(*currentHeader);
795
goForward(currentHeader->length() - 1);
796
// if a paren-header is found add a space after it, if needed
797
// this checks currentLine, appendSpacePad() checks formattedLine
798
// in C# 'catch' can be either a paren or non-paren header
799
if ((!isNonParenHeader || (currentHeader == &AS_CATCH && peekNextChar() == '('))
800
&& charNum < (int) currentLine.length() && !isWhiteSpace(currentLine[charNum+1]))
803
// Signal that a header has been reached
804
// *** But treat a closing while() (as in do...while)
805
// as if it where NOT a header since a closing while()
806
// should never have a block after it!
807
if (!(foundClosingHeader && currentHeader == &AS_WHILE))
810
if (isNonParenHeader)
812
isImmediatelyPostHeader = true;
817
if (currentHeader == &AS_IF && previousHeader == &AS_ELSE)
818
isInLineBreak = false;
820
if (shouldBreakBlocks)
822
if (previousHeader == NULL
823
&& !foundClosingHeader
824
&& !isCharImmediatelyPostOpenBlock)
826
isPrependPostBlockEmptyLineRequested = true;
829
if (currentHeader == &AS_ELSE
830
|| currentHeader == &AS_CATCH
831
|| currentHeader == &AS_FINALLY
832
|| foundClosingHeader)
834
isPrependPostBlockEmptyLineRequested = false;
837
if (shouldBreakClosingHeaderBlocks
838
&& isCharImmediatelyPostCloseBlock)
840
isPrependPostBlockEmptyLineRequested = true;
847
else if ((newHeader = findHeader(preDefinitionHeaders)) != NULL
848
&& parenStack->back() == 0)
850
if (newHeader == &AS_NAMESPACE)
851
foundNamespaceHeader = true;
852
if (newHeader == &AS_CLASS)
853
foundClassHeader = true;
854
foundPreDefinitionHeader = true;
855
appendSequence(*newHeader);
856
goForward(newHeader->length() - 1);
858
if (shouldBreakBlocks)
859
isPrependPostBlockEmptyLineRequested = true;
863
else if ((newHeader = findHeader(preCommandHeaders)) != NULL)
866
|| (*newHeader == AS_CONST && previousCommandChar == ')') // 'const' member functions is a command bracket
867
|| *newHeader == AS_EXTERN)
868
foundPreCommandHeader = true;
869
appendSequence(*newHeader);
870
goForward(newHeader->length() - 1);
874
else if ((newHeader = findHeader(castOperators)) != NULL)
876
foundCastOperator = true;
877
appendSequence(*newHeader);
878
goForward(newHeader->length() - 1);
883
if (findKeyword(currentLine, charNum, "case")
884
|| findKeyword(currentLine, charNum, "default"))
888
if (isInLineBreak) // OK to break line here
891
if (previousNonWSChar == '}' || currentChar == ';')
893
if (shouldBreakOneLineStatements && currentChar == ';'
894
&& (shouldBreakOneLineBlocks || !IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE))
895
//&& (! bracketFormatMode == NONE_MODE)
898
passedSemicolon = true;
901
if (shouldBreakBlocks && currentHeader != NULL && parenStack->back() == 0)
903
isAppendPostBlockEmptyLineRequested = true;
906
if (currentChar != ';')
907
currentHeader = NULL;
909
foundQuestionMark = false;
910
foundNamespaceHeader = false;
911
foundClassHeader = false;
912
foundPreDefinitionHeader = false;
913
foundPreCommandHeader = false;
914
foundCastOperator = false;
915
isInPotentialCalculation = false;
916
isNonInStatementArray = false;
917
isSharpAccessor = false;
920
if (currentChar == ':' && shouldBreakOneLineStatements)
923
&& previousChar != ':' // not part of '::'
924
&& peekNextChar() != ':') // not part of '::'
928
if (shouldBreakBlocks)
929
isPrependPostBlockEmptyLineRequested = true;
932
else if (isCStyle // for C/C++ only
933
&& !foundQuestionMark // not in a ... ? ... : ... sequence
934
&& !foundPreDefinitionHeader // not in a definition block (e.g. class foo : public bar
935
&& previousCommandChar != ')' // not immediately after closing paren of a method header, e.g. ASFormatter::ASFormatter(...) : ASBeautifier(...)
936
&& previousChar != ':' // not part of '::'
937
&& peekNextChar() != ':') // not part of '::'
940
if (shouldBreakBlocks)
941
isPrependPostBlockEmptyLineRequested = true;
945
if (currentChar == '?')
946
foundQuestionMark = true;
948
// determine if this is a potential calculation
949
newHeader = findHeader(operators);
950
// correct mistake of two >> closing a template
951
if (isInTemplate && (newHeader == &AS_GR_GR || newHeader == &AS_GR_GR_GR))
954
if (newHeader != NULL)
956
if (!isInPotentialCalculation)
958
if (find(assignmentOperators.begin(), assignmentOperators.end(), newHeader)
959
!= assignmentOperators.end())
961
char peekedChar = peekNextChar();
962
isInPotentialCalculation = (newHeader != &AS_RETURN
963
&& newHeader != &AS_CIN
964
&& newHeader != &AS_COUT
965
&& newHeader != &AS_CERR
966
&& !(newHeader == &AS_EQUAL && peekedChar == '*')
967
&& !(newHeader == &AS_EQUAL && peekedChar == '&'));
973
// the following are not calculations
974
if (findKeyword(currentLine, charNum, "new"))
975
// if (currentLine.compare(charNum, 3, "new") == 0 && !isLegalNameChar(currentLine[charNum+3]))
976
isInPotentialCalculation = false;
979
if (shouldPadOperators && newHeader != NULL)
981
padOperators(newHeader);
985
if ((shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens)
986
&& (currentChar == '(' || currentChar == ')'))
993
} // end of while loop * end of while loop * end of while loop * end of while loop
995
// return a beautified (i.e. correctly indented) line.
997
string beautifiedLine;
998
size_t readyFormattedLineLength = trim(readyFormattedLine).length();
1000
if (prependEmptyLine // prepend a blank line before this formatted line
1001
&& readyFormattedLineLength > 0
1002
&& previousReadyFormattedLineLength > 0)
1004
isLineReady = true; // signal a waiting readyFormattedLine
1005
beautifiedLine = beautify("");
1006
previousReadyFormattedLineLength = 0;
1008
else // format the current formatted line
1010
isLineReady = false;
1011
beautifiedLine = beautify(readyFormattedLine);
1012
previousReadyFormattedLineLength = readyFormattedLineLength;
1013
lineCommentNoBeautify = lineCommentNoIndent;
1014
lineCommentNoIndent = false;
1015
if (appendOpeningBracket) // insert bracket after this formatted line
1017
appendOpeningBracket = false;
1018
isLineReady = true; // signal a waiting readyFormattedLine
1019
readyFormattedLine = "{";
1020
isPrependPostBlockEmptyLineRequested = false; // next line should not be empty
1021
lineCommentNoIndent = lineCommentNoBeautify; // restore variable
1022
lineCommentNoBeautify = false;
1026
prependEmptyLine = false;
1027
enhance(beautifiedLine); // call the enhancer function
1028
return beautifiedLine;
1033
* check if there are any indented lines ready to be read by nextLine()
1035
* @return are there any indented lines ready?
1037
bool ASFormatter::hasMoreLines() const
1039
return !endOfCodeReached;
1043
* set the bracket formatting mode.
1045
* astyle::NONE_MODE no formatting of brackets.
1046
* astyle::ATTACH_MODE Java, K&R style bracket placement.
1047
* astyle::BREAK_MODE ANSI C/C++ style bracket placement.
1049
* @param mode the bracket formatting mode.
1051
void ASFormatter::setBracketFormatMode(BracketMode mode)
1053
bracketFormatMode = mode;
1057
* set closing header bracket breaking mode
1059
* true brackets just before closing headers (e.g. 'else', 'catch')
1060
* will be broken, even if standard brackets are attached.
1061
* false closing header brackets will be treated as standard brackets.
1063
* @param state the closing header bracket breaking mode.
1065
void ASFormatter::setBreakClosingHeaderBracketsMode(bool state)
1067
shouldBreakClosingHeaderBrackets = state;
1071
* set 'else if()' breaking mode
1073
* true 'else' headers will be broken from their succeeding 'if' headers.
1074
* false 'else' headers will be attached to their succeeding 'if' headers.
1076
* @param state the 'else if()' breaking mode.
1078
void ASFormatter::setBreakElseIfsMode(bool state)
1080
shouldBreakElseIfs = state;
1084
* set operator padding mode.
1086
* true statement operators will be padded with spaces around them.
1087
* false statement operators will not be padded.
1089
* @param state the padding mode.
1091
void ASFormatter::setOperatorPaddingMode(bool state)
1093
shouldPadOperators = state;
1097
* set parenthesis outside padding mode.
1099
* true statement parenthesiss will be padded with spaces around them.
1100
* false statement parenthesiss will not be padded.
1102
* @param state the padding mode.
1104
void ASFormatter::setParensOutsidePaddingMode(bool state)
1106
shouldPadParensOutside = state;
1110
* set parenthesis inside padding mode.
1112
* true statement parenthesis will be padded with spaces around them.
1113
* false statement parenthesis will not be padded.
1115
* @param state the padding mode.
1117
void ASFormatter::setParensInsidePaddingMode(bool state)
1119
shouldPadParensInside = state;
1123
* set parenthesis unpadding mode.
1125
* true statement parenthesis will be unpadded with spaces removed around them.
1126
* false statement parenthesis will not be unpadded.
1128
* @param state the padding mode.
1130
void ASFormatter::setParensUnPaddingMode(bool state)
1132
shouldUnPadParens = state;
1136
* set option to break/not break one-line blocks
1138
* @param state true = break, false = don't break.
1140
void ASFormatter::setBreakOneLineBlocksMode(bool state)
1142
shouldBreakOneLineBlocks = state;
1146
* set option to break/not break lines consisting of multiple statements.
1148
* @param state true = break, false = don't break.
1150
void ASFormatter::setSingleStatementsMode(bool state)
1152
shouldBreakOneLineStatements = state;
1156
* set option to convert tabs to spaces.
1158
* @param state true = convert, false = don't convert.
1160
void ASFormatter::setTabSpaceConversionMode(bool state)
1162
shouldConvertTabs = state;
1167
* set option to break unrelated blocks of code with empty lines.
1169
* @param state true = convert, false = don't convert.
1171
void ASFormatter::setBreakBlocksMode(bool state)
1173
shouldBreakBlocks = state;
1177
* set option to break closing header blocks of code (such as 'else', 'catch', ...) with empty lines.
1179
* @param state true = convert, false = don't convert.
1181
void ASFormatter::setBreakClosingHeaderBlocksMode(bool state)
1183
shouldBreakClosingHeaderBlocks = state;
1187
* jump over several characters.
1189
* @param i the number of characters to jump over.
1191
void ASFormatter::goForward(int i)
1198
* peek at the next unread character.
1200
* @return the next unread character.
1202
char ASFormatter::peekNextChar() const
1205
size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
1207
if (peekNum == string::npos)
1210
ch = currentLine[peekNum];
1216
* check if current placement is before a comment or line-comment
1218
* @return is before a comment or line-comment.
1220
bool ASFormatter::isBeforeComment() const
1222
bool foundComment = false;
1223
size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
1225
if (peekNum == string::npos)
1226
return foundComment;
1228
foundComment = (currentLine.compare(peekNum, 2, "/*") == 0
1229
|| currentLine.compare(peekNum, 2, "//") == 0);
1231
return foundComment;
1235
* check if current placement is before a comment or line-comment
1236
* if a block comment it must be at the end of the line
1238
* @return is before a comment or line-comment.
1240
bool ASFormatter::isBeforeLineEndComment(int startPos) const
1242
bool foundLineEndComment = false;
1243
size_t peekNum = currentLine.find_first_not_of(" \t", startPos + 1);
1245
if (peekNum != string::npos)
1247
if (currentLine.compare(peekNum, 2, "//") == 0)
1248
foundLineEndComment = true;
1249
else if (currentLine.compare(peekNum, 2, "/*") == 0)
1251
// comment must be closed on this line with nothing after it
1252
size_t endNum = currentLine.find("*/", peekNum + 2);
1253
if (endNum != string::npos)
1254
if (currentLine.find_first_not_of(" \t", endNum + 2) == string::npos)
1255
foundLineEndComment = true;
1258
return foundLineEndComment;
1263
* get the next character, increasing the current placement in the process.
1264
* the new character is inserted into the variable currentChar.
1266
* @return whether succeded to receive the new character.
1268
bool ASFormatter::getNextChar()
1270
isInLineBreak = false;
1271
previousChar = currentChar;
1273
if (!isWhiteSpace(currentChar))
1275
previousNonWSChar = currentChar;
1276
if (!isInComment && !isInLineComment && !isInQuote
1277
&& !isImmediatelyPostComment
1278
&& !isImmediatelyPostLineComment
1279
&& !isSequenceReached("/*")
1280
&& !isSequenceReached("//"))
1281
previousCommandChar = currentChar;
1284
int currentLineLength = currentLine.length();
1286
if (charNum + 1 < currentLineLength
1287
&& (!isWhiteSpace(peekNextChar()) || isInComment || isInLineComment))
1289
currentChar = currentLine[++charNum];
1291
if (shouldConvertTabs && currentChar == '\t')
1296
else // end of line has been reached
1298
if (sourceIterator->hasMoreLines())
1300
currentLine = sourceIterator->nextLine();
1301
// reset variables for new line
1305
isInQuoteContinuation = isInVerbatimQuote | haveLineContinuationChar;
1306
haveLineContinuationChar= false;
1308
if (currentLine.length() == 0)
1310
currentLine = string(" "); // a null is inserted if this is not done
1313
// unless reading in the first line of the file,
1314
// break a new line.
1316
isInLineBreak = true;
1320
if (isInLineComment)
1321
isImmediatelyPostLineComment = true;
1322
isInLineComment = false;
1324
// check if is in preprocessor before line trimming
1325
// a blank line after a \ will remove the flag
1326
isImmediatelyPostPreprocessor = isInPreprocessor;
1327
if (previousNonWSChar != '\\'
1328
|| currentLine.find_first_not_of(" \t") == string::npos)
1329
isInPreprocessor = false;
1332
currentChar = currentLine[charNum];
1334
if (shouldConvertTabs && currentChar == '\t')
1341
endOfCodeReached = true;
1348
* jump over the leading white space in the current line,
1349
* IF the line does not begin a comment or is in a preprocessor definition.
1351
void ASFormatter::trimNewLine()
1353
int len = currentLine.length();
1356
if (isInComment || isInPreprocessor || isInQuoteContinuation)
1359
while (isWhiteSpace(currentLine[charNum]) && charNum + 1 < len)
1362
doesLineStartComment = false;
1363
if (isSequenceReached("/*"))
1366
doesLineStartComment = true;
1371
* append a character to the current formatted line.
1372
* Unless disabled (via canBreakLine == false), first check if a
1373
* line-break has been registered, and if so break the
1374
* formatted line, and only then append the character into
1375
* the next formatted line.
1377
* @param ch the character to append.
1378
* @param canBreakLine if true, a registered line-break
1380
void ASFormatter::appendChar(char ch, bool canBreakLine)
1382
if (canBreakLine && isInLineBreak)
1384
formattedLine.append(1, ch);
1388
* append a string sequence to the current formatted line.
1389
* Unless disabled (via canBreakLine == false), first check if a
1390
* line-break has been registered, and if so break the
1391
* formatted line, and only then append the sequence into
1392
* the next formatted line.
1394
* @param sequence the sequence to append.
1395
* @param canBreakLine if true, a registered line-break
1397
void ASFormatter::appendSequence(const string &sequence, bool canBreakLine)
1399
if (canBreakLine && isInLineBreak)
1401
formattedLine.append(sequence);
1405
* append a space to the current formattedline, UNLESS the
1406
* last character is already a white-space character.
1408
void ASFormatter::appendSpacePad()
1410
int len = formattedLine.length();
1411
if (len > 0 && !isWhiteSpace(formattedLine[len-1]))
1413
formattedLine.append(1, ' ');
1419
* append a space to the current formattedline, UNLESS the
1420
* next character is already a white-space character.
1422
void ASFormatter::appendSpaceAfter()
1424
int len = currentLine.length();
1425
if (charNum + 1 < len && !isWhiteSpace(currentLine[charNum+1]))
1427
formattedLine.append(1, ' ');
1433
* register a line break for the formatted line.
1435
void ASFormatter::breakLine()
1438
isInLineBreak = false;
1440
formattedLineCommentNum = string::npos;
1442
// queue an empty line prepend request if one exists
1443
prependEmptyLine = isPrependPostBlockEmptyLineRequested;
1445
readyFormattedLine = formattedLine;
1446
if (isAppendPostBlockEmptyLineRequested)
1448
isAppendPostBlockEmptyLineRequested = false;
1449
isPrependPostBlockEmptyLineRequested = true;
1453
isPrependPostBlockEmptyLineRequested = false;
1460
* check if the currently reached open-bracket (i.e. '{')
1462
* - a definition type block (such as a class or namespace),
1463
* - a command block (such as a method block)
1465
* this method takes for granted that the current character
1466
* is an opening bracket.
1468
* @return the type of the opened block.
1470
BracketType ASFormatter::getBracketType()
1472
BracketType returnVal;
1474
if (previousNonWSChar == '=')
1475
returnVal = ARRAY_TYPE;
1476
else if (foundPreDefinitionHeader)
1478
returnVal = DEFINITION_TYPE;
1479
if (foundNamespaceHeader)
1480
returnVal = (BracketType)(returnVal | NAMESPACE_TYPE);
1481
else if (foundClassHeader)
1482
returnVal = (BracketType)(returnVal | CLASS_TYPE);
1486
bool isCommandType = (foundPreCommandHeader
1487
|| (currentHeader != NULL && isNonParenHeader)
1488
|| (previousCommandChar == ')')
1489
|| (previousCommandChar == ':' && !foundQuestionMark)
1490
|| (previousCommandChar == ';')
1491
|| ((previousCommandChar == '{' || previousCommandChar == '}')
1492
&& isPreviousBracketBlockRelated));
1494
if (!isCommandType && isSharpStyle && isNextWordSharpAccessor())
1496
isCommandType = true;
1497
isSharpAccessor = true;
1500
returnVal = (isCommandType ? COMMAND_TYPE : ARRAY_TYPE);
1503
if (isOneLineBlockReached())
1504
returnVal = (BracketType)(returnVal | SINGLE_LINE_TYPE);
1506
TRbracket(returnVal);
1513
* check if the currently reached '*' or '&' character is
1514
* a pointer-or-reference symbol, or another operator.
1515
* this method takes for granted that the current character
1516
* is either a '*' or '&'.
1518
* @return whether current character is a reference-or-pointer
1520
bool ASFormatter::isPointerOrReference() const
1523
isPR = (!isInPotentialCalculation
1524
|| IS_A(bracketTypeStack->back(), DEFINITION_TYPE)
1525
|| (!isLegalNameChar(previousNonWSChar)
1526
&& previousNonWSChar != ')'
1527
&& previousNonWSChar != ']')
1532
char nextChar = peekNextChar();
1533
isPR |= (!isWhiteSpace(nextChar)
1537
&& !isLegalNameChar(nextChar));
1545
* check if the currently reached '-' character is
1547
* this method takes for granted that the current character
1550
* @return whether the current '-' is a unary minus.
1552
bool ASFormatter::isUnaryMinus() const
1554
return ((previousOperator == &AS_RETURN || !isalnum(previousCommandChar))
1555
&& previousCommandChar != '.'
1556
&& previousCommandChar != ')'
1557
&& previousCommandChar != ']');
1562
* check if the currently reached '-' or '+' character is
1563
* part of an exponent, i.e. 0.2E-5.
1564
* this method takes for granted that the current character
1567
* @return whether the current '-' is in an exponent.
1569
bool ASFormatter::isInExponent() const
1571
int formattedLineLength = formattedLine.length();
1572
if (formattedLineLength >= 2)
1574
char prevPrevFormattedChar = formattedLine[formattedLineLength - 2];
1575
char prevFormattedChar = formattedLine[formattedLineLength - 1];
1577
return ((prevFormattedChar == 'e' || prevFormattedChar == 'E')
1578
&& (prevPrevFormattedChar == '.' || isdigit(prevPrevFormattedChar)));
1585
* check if a one-line bracket has been reached,
1586
* i.e. if the currently reached '{' character is closed
1587
* with a complimentry '}' elsewhere on the current line,
1589
* @return has a one-line bracket been reached?
1591
bool ASFormatter::isOneLineBlockReached() const
1593
bool isInComment = false;
1594
bool isInQuote = false;
1595
int bracketCount = 1;
1596
int currentLineLength = currentLine.length();
1597
char quoteChar = ' ';
1599
for (int i = charNum + 1; i < currentLineLength; ++i)
1601
char ch = currentLine[i];
1605
if (currentLine.compare(i, 2, "*/") == 0)
1607
isInComment = false;
1621
if (ch == quoteChar)
1626
if (ch == '"' || ch == '\'')
1633
if (currentLine.compare(i, 2, "//") == 0)
1636
if (currentLine.compare(i, 2, "/*") == 0)
1648
if (bracketCount == 0)
1656
* check if one of a set of headers has been reached in the
1657
* current position of the current line.
1659
* @return a pointer to the found header. Or a NULL if no header has been reached.
1660
* @param headers a vector of headers.
1661
* @param checkBoundry
1663
const string *ASFormatter::findHeader(const vector<const string*> &headers, bool checkBoundry)
1665
return ASBeautifier::findHeader(currentLine, charNum, headers, checkBoundry);
1669
* check if a line begins with the specified character
1670
* i.e. if the current line begins with a open bracket.
1672
* @return true or false
1674
bool ASFormatter::lineBeginsWith(char charToCheck) const
1676
bool beginsWith = false;
1677
size_t i = currentLine.find_first_not_of(" \t");
1679
if (i != string::npos)
1680
if (currentLine[i] == charToCheck && (int) i == charNum)
1687
* peek at the next word to determine if it is a C# accessor.
1688
* will look ahead in the input file if necessary.
1690
* @return true if the next word is get or set.
1692
bool ASFormatter::isNextWordSharpAccessor() const
1694
bool retVal = false;
1698
firstChar = currentLine.find_first_not_of(" \t", charNum + 1);
1700
if (firstChar != string::npos)
1702
nextLine = currentLine.substr(firstChar);
1707
// find the first non-blank line
1708
while (hasMoreLines())
1710
nextLine = sourceIterator->peekNextLine();
1711
firstChar = nextLine.find_first_not_of(" \t");
1712
if (firstChar != string::npos)
1715
sourceIterator->peekReset();
1719
if (findKeyword(nextLine, firstChar, "get") || findKeyword(nextLine, firstChar, "set"))
1726
* adjust comment position because of adding or deleting spaces
1727
* the spaces are added or deleted to formattedLine
1728
* spacePadNum contains the adjustment
1730
void ASFormatter::adjustComments(void)
1732
assert(spacePadNum != 0);
1733
assert(currentLine.compare(charNum, 2, "//") == 0
1734
|| currentLine.compare(charNum, 2, "/*") == 0);
1737
// block comment must be closed on this line with nothing after it
1738
if (currentLine.compare(charNum, 2, "/*") == 0)
1740
size_t endNum = currentLine.find("*/", charNum + 2);
1741
if (endNum == string::npos)
1743
if (currentLine.find_first_not_of(" \t", endNum + 2) != string::npos)
1747
size_t len = formattedLine.length();
1748
// if spaces were removed, need to add spaces before the comment
1749
if (spacePadNum < 0)
1751
int adjust = -spacePadNum; // make the number positive
1752
if (formattedLine[len-1] != '\t') // don't adjust if a tab
1753
formattedLine.append(adjust, ' ');
1754
// else // comment out to avoid compiler warning
1756
// TRcomment(adjust); // trace macro
1758
// if spaces were added, need to delete spaces before the comment, if possible
1759
else if (spacePadNum > 0)
1761
int adjust = spacePadNum;
1762
if (formattedLine.find_last_not_of(' ') < len - adjust - 1
1763
&& formattedLine[len-1] != '\t') // don't adjust a tab
1764
formattedLine.resize(len - adjust);
1765
// the following are commented out to avoid a Borland compiler warning
1768
TRcomment(-adjust); // trace macro
1773
* append the current bracket inside the end of line comments
1774
* currentChar contains the bracket, it will be appended to formattedLine
1775
* formattedLineCommentNum is the comment location on formattedLine
1777
void ASFormatter::appendCharInsideComments(void)
1779
if (formattedLineCommentNum == string::npos // does the comment start on the previous line?
1780
|| isBeforeComment()) // does a comment follow on this line?
1782
appendCurrentChar(); // don't attach
1785
assert(formattedLine.compare(formattedLineCommentNum, 2, "//") == 0
1786
|| formattedLine.compare(formattedLineCommentNum, 2, "/*") == 0);
1788
// find the previous non space char
1789
size_t end = formattedLineCommentNum;
1790
size_t beg = formattedLine.find_last_not_of(" \t", end-1);
1791
if (beg == string::npos) // is the previous line comment only?
1793
appendCurrentChar(); // don't attach
1798
// insert the bracket
1799
if (end - beg < 3) // is there room to insert?
1800
formattedLine.insert(beg, 3-end+beg, ' ');
1801
if (formattedLine[beg] == '\t') // don't pad with a tab
1802
formattedLine.insert(beg, 1, ' ');
1803
formattedLine[beg+1] = currentChar;
1807
* add or remove space padding to operators
1808
* currentChar contains the paren
1809
* the operators and necessary padding will be appended to formattedLine
1810
* the calling function should have a continue statement after calling this method
1812
* @param *newOperator the operator to be padded
1814
void ASFormatter::padOperators(const string *newOperator)
1816
assert (shouldPadOperators);
1817
assert(newOperator != NULL);
1819
bool shouldPad = (newOperator != &AS_COLON_COLON
1820
&& newOperator != &AS_PAREN_PAREN
1821
&& newOperator != &AS_BLPAREN_BLPAREN
1822
&& newOperator != &AS_PLUS_PLUS
1823
&& newOperator != &AS_MINUS_MINUS
1824
&& newOperator != &AS_NOT
1825
&& newOperator != &AS_BIT_NOT
1826
&& newOperator != &AS_ARROW
1827
&& newOperator != &AS_OPERATOR
1828
&& newOperator != &AS_RETURN
1829
&& !(newOperator == &AS_MINUS && isInExponent())
1830
&& !(newOperator == &AS_MINUS // check for negative number
1831
&& (previousNonWSChar == '('
1832
|| previousNonWSChar == '='
1833
|| previousNonWSChar == ','))
1834
&& !(newOperator == &AS_PLUS && isInExponent())
1835
&& previousOperator != &AS_OPERATOR
1836
&& !((newOperator == &AS_MULT || newOperator == &AS_BIT_AND)
1837
&& isPointerOrReference())
1838
&& !(newOperator == &AS_MULT
1839
&& (previousNonWSChar == '.'
1840
|| previousNonWSChar == '>')) // check for ->
1841
&& !((isInTemplate || isCharImmediatelyPostTemplate)
1842
&& (newOperator == &AS_LS || newOperator == &AS_GR))
1846
// pad before operator
1849
&& !(newOperator == &AS_COLON && !foundQuestionMark)
1850
&& newOperator != &AS_SEMICOLON
1851
&& newOperator != &AS_COMMA)
1853
appendSequence(*newOperator);
1854
goForward(newOperator->length() - 1);
1856
// since this block handles '()' and '[]',
1857
// the parenStack must be updated here accordingly!
1858
if (newOperator == &AS_PAREN_PAREN
1859
|| newOperator == &AS_BLPAREN_BLPAREN)
1860
parenStack->back()--;
1862
currentChar = (*newOperator)[newOperator->length() - 1];
1863
// pad after operator
1864
// but do not pad after a '-' that is a unary-minus.
1867
&& !isBeforeComment()
1868
&& !(newOperator == &AS_MINUS && isUnaryMinus())
1869
&& !(currentLine.compare(charNum + 1, 1, ";") == 0)
1870
&& !(currentLine.compare(charNum + 1, 2, "::") == 0))
1873
previousOperator = newOperator;
1878
* add or remove space padding to parens
1879
* currentChar contains the paren
1880
* the parens and necessary padding will be appended to formattedLine
1881
* the calling function should have a continue statement after calling this method
1883
void ASFormatter::padParens(void)
1885
assert(shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens);
1886
assert (currentChar == '(' || currentChar == ')');
1888
if (currentChar == '(')
1890
int spacesOutsideToDelete = formattedLine.length() - 1;
1891
int spacesInsideToDelete = 0;
1893
// compute spaces outside the opening paren to delete
1894
if (shouldUnPadParens)
1896
char lastChar = ' ';
1897
bool prevIsParenHeader = false;
1898
size_t i = formattedLine.find_last_not_of(" \t");
1899
if (i != string::npos)
1902
spacesOutsideToDelete -= i;
1903
lastChar = formattedLine[i];
1904
// was last word a paren header?
1905
int start; // start of the previous word
1906
for (start = i; start > 0; start--)
1908
if (isLegalNameChar(formattedLine[start]) || formattedLine[start] == '*')
1913
string prevWord = formattedLine.substr(start, end-start+1);
1914
// if previous word is a header, it will be a paren header
1915
const string *prevWordH = ASBeautifier::findHeader(formattedLine, start, headers);
1916
if (prevWordH != NULL)
1918
prevIsParenHeader = true;
1919
TRxtra(*prevWordH); // trace macro
1921
else if (prevWord == "return" // don't unpad return statements
1922
|| prevWord == "*") // don't unpad multiply or pointer
1924
prevIsParenHeader = true;
1925
TRxtra(prevWord); // trace macro
1927
// don't unpad variables
1928
else if (prevWord == "bool"
1929
|| prevWord == "int"
1930
|| prevWord == "void"
1931
|| prevWord == "void*"
1932
|| (prevWord.length() >= 6 // check end of word for _t
1933
&& prevWord.compare(prevWord.length()-2, 2, "_t") == 0)
1934
|| prevWord == "BOOL"
1935
|| prevWord == "DWORD"
1936
|| prevWord == "HWND"
1937
|| prevWord == "INT"
1938
|| prevWord == "LPSTR"
1939
|| prevWord == "VOID"
1940
|| prevWord == "LPVOID"
1943
prevIsParenHeader = true;
1944
TRxtra(prevWord); // trace macro
1947
// do not unpad operators, but leave them if already padded
1948
if (shouldPadParensOutside || prevIsParenHeader)
1949
spacesOutsideToDelete--;
1950
else if (lastChar == '|' // check for ||
1951
|| lastChar == '&' // check for &&
1953
|| (lastChar == '>' && !foundCastOperator)
1961
|| (lastChar == '*' && isInPotentialCalculation)
1964
spacesOutsideToDelete--;
1966
if (spacesOutsideToDelete > 0)
1968
formattedLine.erase(i + 1, spacesOutsideToDelete);
1969
spacePadNum -= spacesOutsideToDelete;
1973
// pad open paren outside
1974
char peekedCharOutside = peekNextChar();
1975
if (shouldPadParensOutside)
1976
if (!(currentChar == '(' && peekedCharOutside == ')'))
1979
appendCurrentChar();
1981
// unpad open paren inside
1982
if (shouldUnPadParens)
1984
size_t j = currentLine.find_first_not_of(" \t", charNum + 1);
1985
if (j != string::npos)
1986
spacesInsideToDelete = j - charNum - 1;
1987
if (shouldPadParensInside)
1988
spacesInsideToDelete--;
1989
if (spacesInsideToDelete > 0)
1991
currentLine.erase(charNum + 1, spacesInsideToDelete);
1992
spacePadNum -= spacesInsideToDelete;
1996
// pad open paren inside
1997
char peekedCharInside = peekNextChar();
1998
if (shouldPadParensInside)
1999
if (!(currentChar == '(' && peekedCharInside == ')'))
2002
TRunpad('(', spacesOutsideToDelete, spacesInsideToDelete); // trace macro
2004
else if (currentChar == ')' /*|| currentChar == ']'*/)
2006
int spacesOutsideToDelete = 0;
2007
int spacesInsideToDelete = formattedLine.length();
2009
// unpad close paren inside
2010
if (shouldUnPadParens)
2012
size_t i = formattedLine.find_last_not_of(" \t");
2013
if (i != string::npos)
2014
spacesInsideToDelete = formattedLine.length() - 1 - i;
2015
if (shouldPadParensInside)
2016
spacesInsideToDelete--;
2017
if (spacesInsideToDelete > 0)
2019
formattedLine.erase(i + 1, spacesInsideToDelete);
2020
spacePadNum -= spacesInsideToDelete;
2024
// pad close paren inside
2025
if (shouldPadParensInside)
2026
if (!(previousChar == '(' && currentChar == ')'))
2029
appendCurrentChar();
2031
// unpad close paren outside
2032
if (shouldUnPadParens)
2034
// may have end of line comments
2035
size_t j = currentLine.find_first_not_of(" \t", charNum + 1);
2036
if (j != string::npos)
2037
if (currentLine[j] == '[' || currentLine[j] == ']')
2038
spacesOutsideToDelete = j - charNum - 1;
2039
if (shouldPadParensOutside)
2040
spacesOutsideToDelete--;
2042
if (spacesOutsideToDelete > 0)
2044
currentLine.erase(charNum + 1, spacesOutsideToDelete);
2045
spacePadNum -= spacesOutsideToDelete;
2049
// pad close paren outside
2050
char peekedCharOutside = peekNextChar();
2051
if (shouldPadParensOutside)
2052
if (peekedCharOutside != ';'
2053
&& peekedCharOutside != ','
2054
&& peekedCharOutside != '.'
2055
&& peekedCharOutside != '-') // check for ->
2058
TRunpad(')', spacesInsideToDelete, 0 /*spacesOutsideToDelete*/); // trace macro
2064
* format brackets as attached or broken
2065
* currentChar contains the bracket
2066
* the brackets will be appended to the current formattedLine or a new formattedLine as necessary
2067
* the calling function should have a continue statement after calling this method
2069
* @param bracketType the type of bracket to be formatted.
2071
void ASFormatter::formatBrackets(BracketType bracketType)
2073
assert(!IS_A(bracketType, ARRAY_TYPE));
2074
assert (currentChar == '{' || currentChar == '}');
2076
if (currentChar == '{')
2078
parenStack->push_back(0);
2080
else if (currentChar == '}')
2082
// parenStack must contain one entry
2083
if (parenStack->size() > 1)
2085
parenStack->pop_back();
2089
if (currentChar == '{')
2091
bool bdacBreak = false;
2092
// should a Linux bracket be broken?
2093
if (bracketFormatMode == BDAC_MODE)
2095
// always break a class
2096
if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], CLASS_TYPE))
2098
// break a namespace and the first bracket if a function
2099
else if (bracketTypeStack->size() <= 2)
2101
if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], NAMESPACE_TYPE)
2102
|| IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], COMMAND_TYPE))
2105
// break the first bracket after a namespace if a function
2106
else if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], NAMESPACE_TYPE))
2108
if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], COMMAND_TYPE))
2111
// if not C style then break the first bracket after a class if a function
2114
if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], CLASS_TYPE)
2115
&& IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], COMMAND_TYPE))
2119
if (bracketFormatMode == ATTACH_MODE
2120
|| (bracketFormatMode == BDAC_MODE && !bdacBreak))
2122
// are there comments before the bracket?
2123
if (isCharImmediatelyPostComment || isCharImmediatelyPostLineComment)
2125
if ((shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE))
2126
&& peekNextChar() != '}'
2127
&& previousCommandChar != '{') // don't attach { {
2128
appendCharInsideComments();
2130
appendCurrentChar(); // don't attach
2132
else if (previousCommandChar == '{'
2133
|| previousCommandChar == '}'
2134
|| previousCommandChar == ';') // '}' , ';' chars added for proper handling of '{' immediately after a '}' or ';'
2136
appendCurrentChar(); // don't attach
2140
// if a blank line preceeds this don't attach
2141
size_t firstChar = formattedLine.find_first_not_of(" \t");
2142
if (firstChar == string::npos)
2143
appendCurrentChar(); // don't attach
2144
else if ((shouldBreakOneLineBlocks
2145
|| !IS_A(bracketType, SINGLE_LINE_TYPE)
2146
|| peekNextChar() == '}')
2147
&& !(isImmediatelyPostPreprocessor
2148
&& lineBeginsWith('{')))
2151
appendCurrentChar(false); // OK to attach
2157
appendCurrentChar(); // don't attach
2161
else if (bracketFormatMode == BREAK_MODE
2162
|| (bracketFormatMode == BDAC_MODE && bdacBreak))
2164
if (isBeforeComment()
2165
&& (shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE)))
2167
// if comment is at line end leave the comment on this line
2168
if (isBeforeLineEndComment(charNum) && !lineBeginsWith('{'))
2170
currentChar = ' '; // remove bracket from current line
2171
appendOpeningBracket = true; // append bracket to following line
2173
// else put comment after the bracket
2177
else if (!IS_A(bracketType, SINGLE_LINE_TYPE))
2179
else if (shouldBreakOneLineBlocks && peekNextChar() != '}')
2181
else if (!isInLineBreak)
2184
appendCurrentChar();
2186
else if (bracketFormatMode == NONE_MODE)
2188
if (lineBeginsWith('{')) // is opening bracket broken?
2189
appendCurrentChar(); // don't attach
2193
appendCurrentChar(false); // OK to attach
2197
else if (currentChar == '}')
2199
// mark state of immediately after empty block
2200
// this state will be used for locating brackets that appear immedately AFTER an empty block (e.g. '{} \n}').
2201
if (previousCommandChar == '{')
2202
isImmediatelyPostEmptyBlock = true;
2204
if ((!(previousCommandChar == '{' && isPreviousBracketBlockRelated)) // this '{' does not close an empty block
2205
&& (shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE)) // astyle is allowed to break on line blocks
2206
// && (!(bracketFormatMode == NONE_MODE && IS_A(bracketType, SINGLE_LINE_TYPE)))
2207
&& !isImmediatelyPostEmptyBlock) // this '}' does not immediately follow an empty block
2210
appendCurrentChar();
2214
if (!isCharImmediatelyPostComment
2215
&& !bracketFormatMode == NONE_MODE
2216
&& !isImmediatelyPostEmptyBlock)
2217
isInLineBreak = false;
2219
appendCurrentChar();
2221
//if (!bracketFormatMode == NONE_MODE)
2222
// if ((shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE))
2223
// && !(currentChar == '}' && peekNextChar() == ';')) // fixes }; placed on separate lines
2224
// shouldBreakLineAfterComments = true;
2227
if (shouldBreakBlocks)
2229
isAppendPostBlockEmptyLineRequested = true;
2236
* format array brackets as attached or broken
2237
* determine if the brackets can have an inStatement indent
2238
* currentChar contains the bracket
2239
* the brackets will be appended to the current formattedLine or a new formattedLine as necessary
2240
* the calling function should have a continue statement after calling this method
2242
* @param bracketType the type of bracket to be formatted, must be an ARRAY_TYPE.
2243
* @param isOpeningArrayBracket indicates if this is the opening bracket for the array block.
2245
void ASFormatter::formatArrayBrackets(BracketType bracketType, bool isOpeningArrayBracket)
2247
assert(IS_A(bracketType, ARRAY_TYPE));
2248
assert (currentChar == '{' || currentChar == '}');
2250
if (currentChar == '{')
2252
// is this the first opening bracket in the array?
2253
if (isOpeningArrayBracket)
2255
if (bracketFormatMode == ATTACH_MODE || bracketFormatMode == BDAC_MODE)
2257
// don't attach to a preprocessor directive
2258
if (isImmediatelyPostPreprocessor && lineBeginsWith('{'))
2260
isInLineBreak = true;
2261
appendCurrentChar(); // don't attach
2263
// are there comments before the bracket?
2264
else if (isCharImmediatelyPostComment || isCharImmediatelyPostLineComment)
2266
appendCharInsideComments();
2270
// if a blank line preceeds this don't attach
2271
size_t firstChar = formattedLine.find_first_not_of(" \t");
2272
if (firstChar == string::npos)
2273
appendCurrentChar(); // don't attach
2276
// if bracket is broken or not an assignment
2277
if (lineBeginsWith('{') || previousNonWSChar != '=')
2279
appendCurrentChar(false); // OK to attach
2283
else if (bracketFormatMode == BREAK_MODE)
2285
if (isWhiteSpace(peekNextChar()))
2287
else if (isBeforeComment())
2289
// do not break unless comment is at line end
2290
if (isBeforeLineEndComment(charNum))
2292
currentChar = ' '; // remove bracket from current line
2293
appendOpeningBracket = true; // append bracket to following line
2296
if (!isInLineBreak && previousNonWSChar != '=')
2298
appendCurrentChar();
2300
else if (bracketFormatMode == NONE_MODE)
2302
if (lineBeginsWith('{')) // is opening bracket broken?
2304
appendCurrentChar(); // don't attach
2308
// if bracket is broken or not an assignment
2309
if (lineBeginsWith('{') || previousNonWSChar != '=')
2311
appendCurrentChar(false); // OK to attach
2316
appendCurrentChar(); // not the first opening bracket - don't change
2318
// if an opening bracket ends the line there will be no inStatement indent
2319
char nextChar = peekNextChar();
2320
if (isWhiteSpace(nextChar)
2321
|| isBeforeLineEndComment(charNum)
2323
isNonInStatementArray = true;
2324
if (isNonInStatementArray)
2330
else if (currentChar == '}')
2332
// does this close the first opening bracket in the array?
2333
if (isOpeningArrayBracket && !IS_A(bracketType, SINGLE_LINE_TYPE) )
2336
appendCurrentChar();
2339
appendCurrentChar();
2344
} // end namespace astyle