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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
40
// can trace only if NDEBUG is not defined
43
// #define TRACEcomment
44
// #define TRACEheader
45
// #define TRACEbracket
47
#if defined(TRACEunpad) || defined(TRACEcomment) || defined(TRACEheader) \
48
|| defined(TRACEbracket) || defined(TRACEarray)
55
#define TRunpad(a,b,c) if(b > 0 || c > 0) *traceOutF << outLineNumber << " " << b << a << c << endl
57
#define TRunpad(a,b,c) ((void)0)
61
#define TRcomment(a) *traceOutF << outLineNumber << " " << a << endl
63
#define TRcomment(a) ((void)0)
67
#define TRxtra(a) *traceOutF << outLineNumber << " " << a << endl
69
#define TRxtra(a) ((void)0)
73
#define TRbracket(a) *traceOutF << outLineNumber << " " << a << endl
75
#define TRbracket(a) ((void)0)
79
#define TRarray(a) *traceOutF << outLineNumber << " " << a << endl
81
#define TRarray(a) ((void)0)
84
#define INIT_CONTAINER(container, value) {if ( (container) != NULL ) delete (container); (container) = (value); }
85
#define DELETE_CONTAINER(container) {if ( (container) != NULL ) delete (container); }
86
#define IS_A(a,b) ( ((a) & (b)) == (b))
92
vector<const string*> ASFormatter::headers;
93
vector<const string*> ASFormatter::nonParenHeaders;
94
vector<const string*> ASFormatter::preDefinitionHeaders;
95
vector<const string*> ASFormatter::preCommandHeaders;
96
vector<const string*> ASFormatter::operators;
97
vector<const string*> ASFormatter::assignmentOperators;
98
vector<const string*> ASFormatter::castOperators;
101
* Constructor of ASFormatter
103
ASFormatter::ASFormatter()
105
preBracketHeaderStack = NULL;
106
bracketTypeStack = NULL;
108
lineCommentNoIndent = false;
109
sourceIterator = NULL;
110
bracketFormatMode = NONE_MODE;
111
shouldPadOperators = false;
112
shouldPadParensOutside = false;
113
shouldPadParensInside = false;
114
shouldUnPadParens = false;
115
shouldBreakOneLineBlocks = true;
116
shouldBreakOneLineStatements = true;
117
shouldConvertTabs = false;
118
shouldBreakBlocks = false;
119
shouldBreakClosingHeaderBlocks = false;
120
shouldBreakClosingHeaderBrackets = false;
121
shouldBreakElseIfs = false;
123
// create a trace text file
124
string filename = "tracef.txt";
125
char* env = getenv("HOME");
127
filename = string(env) + string("/tracef.txt");
130
env = getenv("USERPROFILE");
132
filename = string(env) + string("\\My Documents\\tracef.txt");
135
cout << "\nCould not open tracef.txt\n" << endl;
139
traceOutF = new ofstream(filename.c_str());
144
* Destructor of ASFormatter
146
ASFormatter::~ASFormatter()
148
DELETE_CONTAINER(preBracketHeaderStack);
155
* initialization of static data of ASFormatter.
157
void ASFormatter::staticInit()
159
static int formatterFileType = 9; // initialized with an invalid type
161
if (fileType == formatterFileType) // don't build unless necessary
164
formatterFileType = fileType;
167
nonParenHeaders.clear();
168
assignmentOperators.clear();
170
preDefinitionHeaders.clear();
171
preCommandHeaders.clear();
172
castOperators.clear();
174
ASResource::buildHeaders(headers, fileType);
175
ASResource::buildNonParenHeaders(nonParenHeaders, fileType);
176
ASResource::buildAssignmentOperators(assignmentOperators);
177
ASResource::buildOperators(operators);
178
ASResource::buildPreDefinitionHeaders(preDefinitionHeaders);
179
ASResource::buildPreCommandHeaders(preCommandHeaders);
180
ASResource::buildCastOperators(castOperators);
184
* initialize the ASFormatter.
186
* init() should be called every time a ASFormatter object is to start
187
* formatting a NEW source file.
188
* init() recieves a pointer to a DYNAMICALLY CREATED ASSourceIterator object
189
* that will be used to iterate through the source code. This object will be
190
* deleted during the ASFormatter's destruction, and thus should not be
193
* @param iter a pointer to the DYNAMICALLY CREATED ASSourceIterator object.
195
void ASFormatter::init(ASSourceIterator *si)
199
ASBeautifier::init(si);
200
ASEnhancer::init(ASBeautifier::getIndentLength(),
201
ASBeautifier::getIndentString(),
202
ASBeautifier::getCStyle(),
203
ASBeautifier::getJavaStyle(),
204
ASBeautifier::getSharpStyle(),
205
ASBeautifier::getCaseIndent(),
206
ASBeautifier::getEmptyLineFill());
209
INIT_CONTAINER(preBracketHeaderStack, new vector<const string*>);
210
INIT_CONTAINER(bracketTypeStack, new vector<BracketType>);
211
bracketTypeStack->push_back(NULL_TYPE);
212
INIT_CONTAINER(parenStack, new vector<int>);
213
parenStack->push_back(0);
215
currentHeader = NULL;
216
currentLine = string("");
217
readyFormattedLine = string("");
221
previousCommandChar = ' ';
222
previousNonWSChar = ' ';
226
previousReadyFormattedLineLength = string::npos;
228
previousBracketType = NULL_TYPE;
229
previousOperator = NULL;
232
isInLineComment = false;
234
isInPreprocessor = false;
235
doesLineStartComment = false;
237
isSpecialChar = false;
238
isNonParenHeader = true;
239
foundNamespaceHeader = false;
240
foundClassHeader = false;
241
foundPreDefinitionHeader = false;
242
foundPreCommandHeader = false;
243
foundCastOperator = false;
244
foundQuestionMark = false;
245
isInLineBreak = false;
246
endOfCodeReached = false;
248
isPreviousBracketBlockRelated = true;
249
isInPotentialCalculation = false;
250
shouldReparseCurrentChar = false;
251
passedSemicolon = false;
253
isInTemplate = false;
255
shouldBreakLineAfterComments = false;
256
isImmediatelyPostComment = false;
257
isImmediatelyPostLineComment = false;
258
isImmediatelyPostEmptyBlock = false;
259
isImmediatelyPostPreprocessor = false;
261
isPrependPostBlockEmptyLineRequested = false;
262
isAppendPostBlockEmptyLineRequested = false;
263
prependEmptyLine = false;
264
appendOpeningBracket = false;
266
foundClosingHeader = false;
267
previousReadyFormattedLineLength = 0;
269
isImmediatelyPostHeader = false;
272
// fileName will be empty if ASTYLE_LIB is defined
273
if (fileName.empty())
274
*traceOutF << "new file" << endl;
276
*traceOutF << fileName << 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;
300
if (shouldReparseCurrentChar)
301
shouldReparseCurrentChar = false;
302
else if (!getNextChar())
305
return beautify(readyFormattedLine);
307
else // stuff to do when reading a new character...
309
// make sure that a virgin '{' at the begining ofthe file will be treated as a block...
310
if (isInVirginLine && currentChar == '{')
311
previousCommandChar = '{';
312
isPreviousCharPostComment = isCharImmediatelyPostComment;
313
isCharImmediatelyPostComment = false;
314
isCharImmediatelyPostTemplate = false;
317
//if (inLineNumber >= 185)
324
// explicitely break a line when a line comment's end is found.
325
if (charNum + 1 == (int) currentLine.length())
327
isInLineBreak = true;
328
isInLineComment = false;
329
isImmediatelyPostLineComment = true;
330
currentChar = 0; //make sure it is a neutral char.
334
else if (isInComment)
336
if (isSequenceReached("*/"))
339
isImmediatelyPostComment = true;
340
appendSequence(AS_CLOSE_COMMENT);
349
// not in line comment or comment
355
isSpecialChar = false;
358
else if (currentChar == '\\')
360
isSpecialChar = true;
363
else if (quoteChar == currentChar)
376
// handle white space - needed to simplify the rest.
377
if (isWhiteSpace(currentChar) || isInPreprocessor)
383
/* not in MIDDLE of quote or comment or white-space of any type ... */
385
if (isSequenceReached("//"))
387
if (currentLine[charNum+2] == '\xf2') // check for windows line marker
388
isAppendPostBlockEmptyLineRequested = false;
389
isInLineComment = true;
390
// do not indent if in column 1 or 2
391
if (lineCommentNoIndent == false)
394
lineCommentNoIndent = true;
395
else if (charNum == 1 && currentLine[0] == ' ')
396
lineCommentNoIndent = true;
398
// move comment if spaces were added or deleted
399
if (lineCommentNoIndent == false && spacePadNum != 0)
401
formattedLineCommentNum = formattedLine.length();
402
appendSequence(AS_OPEN_LINE_COMMENT);
404
// explicitely break a line when a line comment's end is found.
405
if (charNum + 1 == (int) currentLine.length())
407
isInLineBreak = true;
408
isInLineComment = false;
409
isImmediatelyPostLineComment = true;
410
currentChar = 0; //make sure it is a neutral char.
414
else if (isSequenceReached("/*"))
417
if (spacePadNum != 0)
419
formattedLineCommentNum = formattedLine.length();
420
appendSequence(AS_OPEN_COMMENT);
424
else if (currentChar == '"' || currentChar == '\'')
427
quoteChar = currentChar;
432
/* not in quote or comment or white-space of any type ... */
434
// check if in preprocessor
435
// ** isInPreprocessor will be automatically reset at the begining
436
// of a new line in getnextChar()
437
if (currentChar == '#')
439
isInPreprocessor = true;
444
/* not in preprocessor ... */
446
if (isImmediatelyPostComment)
448
isImmediatelyPostComment = false;
449
isCharImmediatelyPostComment = true;
452
if (isImmediatelyPostLineComment)
454
isImmediatelyPostLineComment = false;
455
isCharImmediatelyPostLineComment = true;
458
if (shouldBreakLineAfterComments)
460
shouldBreakLineAfterComments = false;
461
shouldReparseCurrentChar = true;
466
// reset isImmediatelyPostHeader information
467
if (isImmediatelyPostHeader)
469
isImmediatelyPostHeader = false;
471
// Make sure headers are broken from their succeeding blocks
473
// if (isFoo) DoBar();
478
// But treat else if() as a special case which should not be broken!
479
if (shouldBreakOneLineStatements)
481
// if may break 'else if()'s, then simply break the line
483
if (shouldBreakElseIfs)
484
isInLineBreak = true;
488
if (passedSemicolon) // need to break the formattedLine
490
passedSemicolon = false;
491
if (parenStack->back() == 0 && currentChar != ';') // allow ;;
493
// does a one-line statement have ending comments?
494
if (IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE))
496
size_t blockEnd = currentLine.rfind(AS_CLOSE_BRACKET);
497
assert(blockEnd != string::npos);
498
// move ending comments to this formattedLine
499
if (isBeforeLineEndComment(blockEnd))
501
size_t commentStart = currentLine.find_first_not_of(" \t", blockEnd + 1);
502
assert(commentStart != string::npos);
503
assert((currentLine.compare(commentStart, 2, "//") == 0)
504
|| (currentLine.compare(commentStart, 2, "/*") == 0));
505
size_t commentLength = currentLine.length() - commentStart;
506
int tabCount = getIndentLength();
508
for (int i=1; i<tabCount; i++)
509
formattedLine.append(1, ' ');
510
formattedLine.append(currentLine, commentStart, commentLength);
511
currentLine.erase(commentStart, commentLength);
514
shouldReparseCurrentChar = true;
515
isInLineBreak = true;
523
if (parenStack->back() == 0 && !isBeforeComment())
525
shouldReparseCurrentChar = true;
526
isInLineBreak = true;
531
// Check if in template declaration, e.g. foo<bar> or foo<bar,fig>
532
// If so, set isInTemplate to true
533
if (!isInTemplate && currentChar == '<')
535
int maxTemplateDepth = 0;
538
for (size_t i = charNum;
539
i < currentLine.length();
540
i += (oper ? oper->length() : 1))
542
oper = ASBeautifier::findHeader(currentLine, i, operators);
549
else if (oper == &AS_GR)
552
if (templateDepth == 0)
554
// this is a template!
556
templateDepth = maxTemplateDepth;
560
else if (oper == &AS_COMMA // comma, e.g. A<int, char>
561
|| oper == &AS_BIT_AND // reference, e.g. A<int&>
562
|| oper == &AS_MULT // pointer, e.g. A<int*>
563
|| oper == &AS_COLON_COLON) // ::, e.g. std::string
567
else if (!isLegalNameChar(currentLine[i]) && !isWhiteSpace(currentLine[i]))
569
// this is not a template -> leave...
570
isInTemplate = false;
576
// handle parenthesies
577
if (currentChar == '(' || currentChar == '[' || (isInTemplate && currentChar == '<'))
579
parenStack->back()++;
580
if (currentChar == '[')
583
else if (currentChar == ')' || currentChar == ']' || (isInTemplate && currentChar == '>'))
585
parenStack->back()--;
586
if (isInTemplate && currentChar == '>')
589
if (templateDepth == 0)
591
isInTemplate = false;
592
isCharImmediatelyPostTemplate = true;
596
// check if this parenthesis closes a header, e.g. if (...), while (...)
597
if (isInHeader && parenStack->back() == 0)
600
isImmediatelyPostHeader = true;
602
if (currentChar == ']')
604
if (currentChar == ')')
605
foundCastOperator = false;
609
if (currentChar == '{' || currentChar == '}')
611
if (currentChar == '{')
613
BracketType newBracketType = getBracketType();
614
foundNamespaceHeader = false;
615
foundClassHeader = false;
616
foundPreDefinitionHeader = false;
617
foundPreCommandHeader = false;
618
isInPotentialCalculation = false;
620
bracketTypeStack->push_back(newBracketType);
621
preBracketHeaderStack->push_back(currentHeader);
622
currentHeader = NULL;
624
isPreviousBracketBlockRelated = !IS_A(newBracketType, ARRAY_TYPE);
627
// this must be done before the bracketTypeStack is popped
628
BracketType bracketType = bracketTypeStack->back();
629
bool isOpeningArrayBracket = (IS_A(bracketType, ARRAY_TYPE)
630
&& bracketTypeStack->size() >= 2
631
&& !IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], ARRAY_TYPE)
634
if (currentChar == '}')
636
// if a request has been made to append a post block empty line,
637
// but the block exists immediately before a closing bracket,
638
// then there is not need for the post block empty line.
640
isAppendPostBlockEmptyLineRequested = false;
642
if (!bracketTypeStack->empty())
644
previousBracketType = bracketTypeStack->back();
645
bracketTypeStack->pop_back();
646
isPreviousBracketBlockRelated = !IS_A(bracketType, ARRAY_TYPE);
649
if (!preBracketHeaderStack->empty())
651
currentHeader = preBracketHeaderStack->back();
652
preBracketHeaderStack->pop_back();
655
currentHeader = NULL;
659
if (IS_A(bracketType, ARRAY_TYPE))
660
formatArrayBrackets(bracketType, isOpeningArrayBracket);
662
formatBrackets(bracketType);
666
if (((previousCommandChar == '{' && isPreviousBracketBlockRelated)
667
|| (previousCommandChar == '}'
668
&& bracketFormatMode != NONE_MODE
669
&& !isImmediatelyPostEmptyBlock
670
&& isPreviousBracketBlockRelated
671
&& !isPreviousCharPostComment // Fixes wrongly appended newlines after '}' immediately after comments
672
&& peekNextChar() != ' '
673
&& !IS_A(previousBracketType, DEFINITION_TYPE)
674
&& !(ASBeautifier::isJavaStyle && currentChar == ')'))
675
&& !IS_A(bracketTypeStack->back(), DEFINITION_TYPE))
676
&& (shouldBreakOneLineBlocks
677
|| !IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE)))
679
isCharImmediatelyPostOpenBlock = (previousCommandChar == '{');
680
isCharImmediatelyPostCloseBlock = (previousCommandChar == '}');
682
//if (bracketFormatMode != NONE_MODE)
684
previousCommandChar = ' ';
685
isInLineBreak = true;
689
// reset block handling flags
690
isImmediatelyPostEmptyBlock = false;
695
if ((newHeader = findHeader(headers)) != NULL)
697
foundClosingHeader = false;
698
const string *previousHeader;
700
// recognize closing headers of do..while, if..else, try..catch..finally
701
if ((newHeader == &AS_ELSE && currentHeader == &AS_IF)
702
|| (newHeader == &AS_WHILE && currentHeader == &AS_DO)
703
|| (newHeader == &AS_CATCH && currentHeader == &AS_TRY)
704
|| (newHeader == &AS_CATCH && currentHeader == &AS_CATCH)
705
|| (newHeader == &AS_FINALLY && currentHeader == &AS_TRY)
706
|| (newHeader == &AS_FINALLY && currentHeader == &AS_CATCH))
707
foundClosingHeader = true;
709
previousHeader = currentHeader;
710
currentHeader = newHeader;
712
// If in ATTACH or LINUX bracket modes, attach closing headers (e.g. 'else', 'catch')
713
// to their preceding bracket,
714
// But do not perform the attachment if the shouldBreakClosingHeaderBrackets is set!
715
if (!shouldBreakClosingHeaderBrackets
716
&& foundClosingHeader
717
&& (bracketFormatMode == ATTACH_MODE || bracketFormatMode == BDAC_MODE)
718
&& (shouldBreakOneLineBlocks || !IS_A(previousBracketType, SINGLE_LINE_TYPE))
719
&& previousNonWSChar == '}')
721
spacePadNum = 0; // don't count as padding
723
size_t firstChar = formattedLine.find_first_not_of(" \t");
724
if (firstChar != string::npos) // if a blank line does not preceed this
726
isInLineBreak = false;
730
if (shouldBreakBlocks)
731
isAppendPostBlockEmptyLineRequested = false;
734
// If NONE bracket mode, leave closing headers as they are (e.g. 'else', 'catch')
735
if (foundClosingHeader && bracketFormatMode == NONE_MODE && previousCommandChar == '}')
737
if (lineBeginsWith('}')) // is closing bracket broken?
739
isInLineBreak = false;
743
if (shouldBreakBlocks)
744
isAppendPostBlockEmptyLineRequested = false;
747
if (foundClosingHeader && bracketFormatMode == BREAK_MODE && previousCommandChar == '}')
750
//Check if a template definition as been reached, e.g. template<class A>
751
//if (newHeader == &AS_TEMPLATE)
753
// isInTemplate = true;
756
// check if the found header is non-paren header
757
isNonParenHeader = (find(nonParenHeaders.begin(), nonParenHeaders.end(),
758
newHeader) != nonParenHeaders.end());
760
appendSequence(*currentHeader);
761
goForward(currentHeader->length() - 1);
762
// if a paren-header is found add a space after it, if needed
763
// this checks currentLine, appendSpacePad() checks formattedLine
764
if (!isNonParenHeader && charNum < (int) currentLine.length() && !isWhiteSpace(currentLine[charNum+1]))
767
// Signal that a header has been reached
768
// *** But treat a closing while() (as in do...while)
769
// as if it where NOT a header since a closing while()
770
// should never have a block after it!
771
if (!(foundClosingHeader && currentHeader == &AS_WHILE))
774
if (isNonParenHeader)
776
isImmediatelyPostHeader = true;
781
if (currentHeader == &AS_IF && previousHeader == &AS_ELSE)
782
isInLineBreak = false;
784
if (shouldBreakBlocks)
786
if (previousHeader == NULL
787
&& !foundClosingHeader
788
&& !isCharImmediatelyPostOpenBlock)
790
isPrependPostBlockEmptyLineRequested = true;
793
if (currentHeader == &AS_ELSE
794
|| currentHeader == &AS_CATCH
795
|| currentHeader == &AS_FINALLY
796
|| foundClosingHeader)
798
isPrependPostBlockEmptyLineRequested = false;
801
if (shouldBreakClosingHeaderBlocks
802
&& isCharImmediatelyPostCloseBlock)
804
isPrependPostBlockEmptyLineRequested = true;
811
else if ((newHeader = findHeader(preDefinitionHeaders)) != NULL
812
&& parenStack->back() == 0)
814
if (newHeader == &AS_NAMESPACE)
815
foundNamespaceHeader = true;
816
if (newHeader == &AS_CLASS)
817
foundClassHeader = true;
818
foundPreDefinitionHeader = true;
819
appendSequence(*newHeader);
820
goForward(newHeader->length() - 1);
822
if (shouldBreakBlocks)
823
isPrependPostBlockEmptyLineRequested = true;
827
else if ((newHeader = findHeader(preCommandHeaders)) != NULL)
829
if (ASBeautifier::isJavaStyle
830
|| (*newHeader == AS_CONST && previousCommandChar == ')') // 'const' member functions is a command bracket
831
|| *newHeader == AS_EXTERN)
832
foundPreCommandHeader = true;
833
appendSequence(*newHeader);
834
goForward(newHeader->length() - 1);
838
else if ((newHeader = findHeader(castOperators)) != NULL)
840
foundCastOperator = true;
841
appendSequence(*newHeader);
842
goForward(newHeader->length() - 1);
849
if (isInLineBreak) // OK to break line here
852
if (previousNonWSChar == '}' || currentChar == ';')
854
if (shouldBreakOneLineStatements && currentChar == ';'
855
&& (shouldBreakOneLineBlocks || !IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE))
856
//&& (! bracketFormatMode == NONE_MODE)
859
passedSemicolon = true;
862
if (shouldBreakBlocks && currentHeader != NULL && parenStack->back() == 0)
864
isAppendPostBlockEmptyLineRequested = true;
867
if (currentChar != ';')
868
currentHeader = NULL;
870
foundQuestionMark = false;
871
foundNamespaceHeader = false;
872
foundClassHeader = false;
873
foundPreDefinitionHeader = false;
874
foundPreCommandHeader = false;
875
foundCastOperator = false;
876
isInPotentialCalculation = false;
877
isNonInStatementArray = false;
880
if (currentChar == ':'
881
&& shouldBreakOneLineStatements
882
&& !foundQuestionMark // not in a ... ? ... : ... sequence
883
&& !foundPreDefinitionHeader // not in a definition block (e.g. class foo : public bar
884
&& previousCommandChar != ')' // not immediately after closing paren of a method header, e.g. ASFormatter::ASFormatter(...) : ASBeautifier(...)
885
&& previousChar != ':' // not part of '::'
886
&& peekNextChar() != ':') // not part of '::'
889
if (shouldBreakBlocks)
890
isPrependPostBlockEmptyLineRequested = true;
893
if (currentChar == '?')
894
foundQuestionMark = true;
896
// determine if this is a potential calculation
897
newHeader = findHeader(operators);
899
if (newHeader != NULL)
901
if (!isInPotentialCalculation)
903
if (find(assignmentOperators.begin(), assignmentOperators.end(), newHeader)
904
!= assignmentOperators.end())
906
char peekedChar = peekNextChar();
907
isInPotentialCalculation = (newHeader != &AS_RETURN
908
&& !(newHeader == &AS_EQUAL && peekedChar == '*')
909
&& !(newHeader == &AS_EQUAL && peekedChar == '&'));
915
// the following are not calculations
916
if (currentLine.compare(charNum, 3, "new") == 0 && !isLegalNameChar(currentLine[charNum+3]))
917
isInPotentialCalculation = false;
920
if (shouldPadOperators && newHeader != NULL)
922
padOperators(newHeader);
926
if ((shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens)
927
&& (currentChar == '(' || currentChar == ')'))
934
} // end of while loop * end of while loop * end of while loop * end of while loop
936
// return a beautified (i.e. correctly indented) line.
938
string beautifiedLine;
939
size_t readyFormattedLineLength = trim(readyFormattedLine).length();
941
if (prependEmptyLine // prepend a blank line before this formatted line
942
&& readyFormattedLineLength > 0
943
&& previousReadyFormattedLineLength > 0)
945
isLineReady = true; // signal that a readyFormattedLine is still waiting
946
beautifiedLine = beautify("");
947
previousReadyFormattedLineLength = 0;
949
else // format the current formatted line
952
beautifiedLine = beautify(readyFormattedLine);
953
previousReadyFormattedLineLength = readyFormattedLineLength;
954
lineCommentNoBeautify = lineCommentNoIndent;
955
lineCommentNoIndent = false;
956
if (appendOpeningBracket) // insert bracket after this formatted line
958
appendOpeningBracket = false;
959
isLineReady = true; // signal that a readyFormattedLine is still waiting
960
readyFormattedLine = "{";
961
isPrependPostBlockEmptyLineRequested = false; // next line should not be empty
965
prependEmptyLine = false;
966
enhance(beautifiedLine); // call the enhancer function
967
return beautifiedLine;
972
* check if there are any indented lines ready to be read by nextLine()
974
* @return are there any indented lines ready?
976
bool ASFormatter::hasMoreLines() const
978
return !endOfCodeReached;
982
* set the bracket formatting mode.
984
* astyle::NONE_MODE no formatting of brackets.
985
* astyle::ATTACH_MODE Java, K&R style bracket placement.
986
* astyle::BREAK_MODE ANSI C/C++ style bracket placement.
988
* @param mode the bracket formatting mode.
990
void ASFormatter::setBracketFormatMode(BracketMode mode)
992
bracketFormatMode = mode;
996
* set closing header bracket breaking mode
998
* true brackets just before closing headers (e.g. 'else', 'catch')
999
* will be broken, even if standard brackets are attached.
1000
* false closing header brackets will be treated as standard brackets.
1002
* @param state the closing header bracket breaking mode.
1004
void ASFormatter::setBreakClosingHeaderBracketsMode(bool state)
1006
shouldBreakClosingHeaderBrackets = state;
1010
* set 'else if()' breaking mode
1012
* true 'else' headers will be broken from their succeeding 'if' headers.
1013
* false 'else' headers will be attached to their succeeding 'if' headers.
1015
* @param state the 'else if()' breaking mode.
1017
void ASFormatter::setBreakElseIfsMode(bool state)
1019
shouldBreakElseIfs = state;
1023
* set operator padding mode.
1025
* true statement operators will be padded with spaces around them.
1026
* false statement operators will not be padded.
1028
* @param state the padding mode.
1030
void ASFormatter::setOperatorPaddingMode(bool state)
1032
shouldPadOperators = state;
1036
* set parenthesis outside padding mode.
1038
* true statement parenthesiss will be padded with spaces around them.
1039
* false statement parenthesiss will not be padded.
1041
* @param state the padding mode.
1043
void ASFormatter::setParensOutsidePaddingMode(bool state)
1045
shouldPadParensOutside = state;
1049
* set parenthesis inside padding mode.
1051
* true statement parenthesis will be padded with spaces around them.
1052
* false statement parenthesis will not be padded.
1054
* @param state the padding mode.
1056
void ASFormatter::setParensInsidePaddingMode(bool state)
1058
shouldPadParensInside = state;
1062
* set parenthesis unpadding mode.
1064
* true statement parenthesis will be unpadded with spaces removed around them.
1065
* false statement parenthesis will not be unpadded.
1067
* @param state the padding mode.
1069
void ASFormatter::setParensUnPaddingMode(bool state)
1071
shouldUnPadParens = state;
1075
* set option to break/not break one-line blocks
1077
* @param state true = break, false = don't break.
1079
void ASFormatter::setBreakOneLineBlocksMode(bool state)
1081
shouldBreakOneLineBlocks = state;
1085
* set option to break/not break lines consisting of multiple statements.
1087
* @param state true = break, false = don't break.
1089
void ASFormatter::setSingleStatementsMode(bool state)
1091
shouldBreakOneLineStatements = state;
1095
* set option to convert tabs to spaces.
1097
* @param state true = convert, false = don't convert.
1099
void ASFormatter::setTabSpaceConversionMode(bool state)
1101
shouldConvertTabs = state;
1106
* set option to break unrelated blocks of code with empty lines.
1108
* @param state true = convert, false = don't convert.
1110
void ASFormatter::setBreakBlocksMode(bool state)
1112
shouldBreakBlocks = state;
1116
* set option to break closing header blocks of code (such as 'else', 'catch', ...) with empty lines.
1118
* @param state true = convert, false = don't convert.
1120
void ASFormatter::setBreakClosingHeaderBlocksMode(bool state)
1122
shouldBreakClosingHeaderBlocks = state;
1126
* jump over several characters.
1128
* @param i the number of characters to jump over.
1130
void ASFormatter::goForward(int i)
1137
* peek at the next unread character.
1139
* @return the next unread character.
1141
char ASFormatter::peekNextChar() const
1144
size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
1146
if (peekNum == string::npos)
1149
ch = currentLine[peekNum];
1151
// if (shouldConvertTabs && ch == '\t')
1158
* check if current placement is before a comment or line-comment
1160
* @return is before a comment or line-comment.
1162
bool ASFormatter::isBeforeComment() const
1164
bool foundComment = false;
1165
size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
1167
if (peekNum == string::npos)
1168
return foundComment;
1170
foundComment = (currentLine.compare(peekNum, 2, "/*") == 0
1171
|| currentLine.compare(peekNum, 2, "//") == 0);
1173
return foundComment;
1177
* check if current placement is before a comment or line-comment
1178
* if a block comment it must be at the end of the line
1180
* @return is before a comment or line-comment.
1182
bool ASFormatter::isBeforeLineEndComment(int startPos) const
1184
bool foundLineEndComment = false;
1185
size_t peekNum = currentLine.find_first_not_of(" \t", startPos + 1);
1187
if (peekNum != string::npos)
1189
if (currentLine.compare(peekNum, 2, "//") == 0)
1190
foundLineEndComment = true;
1191
else if (currentLine.compare(peekNum, 2, "/*") == 0)
1193
// comment must be closed on this line with nothing after it
1194
size_t endNum = currentLine.find("*/", peekNum + 2);
1195
if (endNum != string::npos)
1196
if (currentLine.find_first_not_of(" \t", endNum + 2) == string::npos)
1197
foundLineEndComment = true;
1200
return foundLineEndComment;
1205
* get the next character, increasing the current placement in the process.
1206
* the new character is inserted into the variable currentChar.
1208
* @return whether succeded to recieve the new character.
1210
bool ASFormatter::getNextChar()
1212
isInLineBreak = false;
1213
previousChar = currentChar;
1215
if (!isWhiteSpace(currentChar))
1217
previousNonWSChar = currentChar;
1218
if (!isInComment && !isInLineComment && !isInQuote
1219
&& !isImmediatelyPostComment
1220
&& !isImmediatelyPostLineComment
1221
&& !isSequenceReached("/*")
1222
&& !isSequenceReached("//"))
1223
previousCommandChar = previousNonWSChar;
1226
int currentLineLength = currentLine.length();
1228
if (charNum + 1 < currentLineLength
1229
&& (!isWhiteSpace(peekNextChar()) || isInComment || isInLineComment))
1231
currentChar = currentLine[++charNum];
1233
if (shouldConvertTabs && currentChar == '\t')
1238
else // end of line has been reached
1240
if (sourceIterator->hasMoreLines())
1242
currentLine = sourceIterator->nextLine();
1246
if (currentLine.length() == 0)
1248
currentLine = string(" "); // a null is inserted if this is not done
1251
// unless reading in the first line of the file,
1252
// break a new line.
1254
isInLineBreak = true;
1258
if (isInLineComment)
1259
isImmediatelyPostLineComment = true;
1260
isInLineComment = false;
1262
// check if is in preprocessor before line trimming
1263
isImmediatelyPostPreprocessor = isInPreprocessor;
1264
if (previousNonWSChar != '\\')
1265
isInPreprocessor = false;
1268
currentChar = currentLine[charNum];
1270
if (shouldConvertTabs && currentChar == '\t')
1277
endOfCodeReached = true;
1284
* jump over the leading white space in the current line,
1285
* IF the line does not begin a comment or is in a preprocessor definition.
1287
void ASFormatter::trimNewLine()
1289
int len = currentLine.length();
1292
if (isInComment || isInPreprocessor)
1295
while (isWhiteSpace(currentLine[charNum]) && charNum + 1 < len)
1298
doesLineStartComment = false;
1299
if (isSequenceReached("/*"))
1302
doesLineStartComment = true;
1307
* append a character to the current formatted line.
1308
* Unless disabled (via canBreakLine == false), first check if a
1309
* line-break has been registered, and if so break the
1310
* formatted line, and only then append the character into
1311
* the next formatted line.
1313
* @param ch the character to append.
1314
* @param canBreakLine if true, a registered line-break
1316
void ASFormatter::appendChar(char ch, bool canBreakLine)
1318
if (canBreakLine && isInLineBreak)
1320
formattedLine.append(1, ch);
1324
* append a string sequence to the current formatted line.
1325
* Unless disabled (via canBreakLine == false), first check if a
1326
* line-break has been registered, and if so break the
1327
* formatted line, and only then append the sequence into
1328
* the next formatted line.
1330
* @param sequence the sequence to append.
1331
* @param canBreakLine if true, a registered line-break
1333
void ASFormatter::appendSequence(const string &sequence, bool canBreakLine)
1335
if (canBreakLine && isInLineBreak)
1337
formattedLine.append(sequence);
1341
* append a space to the current formattedline, UNLESS the
1342
* last character is already a white-space character.
1344
void ASFormatter::appendSpacePad()
1346
int len = formattedLine.length();
1347
if (len > 0 && !isWhiteSpace(formattedLine[len-1]))
1349
formattedLine.append(1, ' ');
1355
* append a space to the current formattedline, UNLESS the
1356
* next character is already a white-space character.
1358
void ASFormatter::appendSpaceAfter()
1360
int len = currentLine.length();
1361
if (charNum + 1 < len && !isWhiteSpace(currentLine[charNum+1]))
1363
formattedLine.append(1, ' ');
1369
* register a line break for the formatted line.
1371
void ASFormatter::breakLine()
1374
isInLineBreak = false;
1376
formattedLineCommentNum = string::npos;
1378
// queue an empty line prepend request if one exists
1379
prependEmptyLine = isPrependPostBlockEmptyLineRequested;
1381
readyFormattedLine = formattedLine;
1382
if (isAppendPostBlockEmptyLineRequested)
1384
isAppendPostBlockEmptyLineRequested = false;
1385
isPrependPostBlockEmptyLineRequested = true;
1389
isPrependPostBlockEmptyLineRequested = false;
1396
* check if the currently reached open-bracket (i.e. '{')
1398
* - a definition type block (such as a class or namespace),
1399
* - a command block (such as a method block)
1401
* this method takes for granted that the current character
1402
* is an opening bracket.
1404
* @return the type of the opened block.
1406
BracketType ASFormatter::getBracketType() const
1408
BracketType returnVal;
1410
if (foundPreDefinitionHeader)
1412
returnVal = DEFINITION_TYPE;
1413
if (foundNamespaceHeader)
1414
returnVal = (BracketType)(returnVal | NAMESPACE_TYPE);
1415
else if (foundClassHeader)
1416
returnVal = (BracketType)(returnVal | CLASS_TYPE);
1420
bool isCommandType = false;
1422
if (previousNonWSChar != '=')
1423
isCommandType = (foundPreCommandHeader
1424
|| (currentHeader != NULL && isNonParenHeader)
1425
|| (previousCommandChar == ')')
1426
|| (previousCommandChar == ':' && !foundQuestionMark)
1427
|| (previousCommandChar == ';')
1428
|| ((previousCommandChar == '{' || previousCommandChar == '}')
1429
&& isPreviousBracketBlockRelated));
1431
returnVal = (isCommandType ? COMMAND_TYPE : ARRAY_TYPE);
1434
if (isOneLineBlockReached())
1435
returnVal = (BracketType)(returnVal | SINGLE_LINE_TYPE);
1437
TRbracket(returnVal);
1442
* check if the currently reached '*' or '&' character is
1443
* a pointer-or-reference symbol, or another operator.
1444
* this method takes for granted that the current character
1445
* is either a '*' or '&'.
1447
* @return whether current character is a reference-or-pointer
1449
bool ASFormatter::isPointerOrReference() const
1452
isPR = (!isInPotentialCalculation
1453
|| IS_A(bracketTypeStack->back(), DEFINITION_TYPE)
1454
|| (!isLegalNameChar(previousNonWSChar)
1455
&& previousNonWSChar != ')'
1456
&& previousNonWSChar != ']')
1461
char nextChar = peekNextChar();
1462
isPR |= (!isWhiteSpace(nextChar)
1466
&& !isLegalNameChar(nextChar));
1474
* check if the currently reached '-' character is
1476
* this method takes for granted that the current character
1479
* @return whether the current '-' is a unary minus.
1481
bool ASFormatter::isUnaryMinus() const
1483
return ((previousOperator == &AS_RETURN || !isalnum(previousCommandChar))
1484
&& previousCommandChar != '.'
1485
&& previousCommandChar != ')'
1486
&& previousCommandChar != ']');
1491
* check if the currently reached '-' or '+' character is
1492
* part of an exponent, i.e. 0.2E-5.
1493
* this method takes for granted that the current character
1496
* @return whether the current '-' is in an exponent.
1498
bool ASFormatter::isInExponent() const
1500
int formattedLineLength = formattedLine.length();
1501
if (formattedLineLength >= 2)
1503
char prevPrevFormattedChar = formattedLine[formattedLineLength - 2];
1504
char prevFormattedChar = formattedLine[formattedLineLength - 1];
1506
return ((prevFormattedChar == 'e' || prevFormattedChar == 'E')
1507
&& (prevPrevFormattedChar == '.' || isdigit(prevPrevFormattedChar)));
1514
* check if a one-line bracket has been reached,
1515
* i.e. if the currently reached '{' character is closed
1516
* with a complimentry '}' elsewhere on the current line,
1518
* @return has a one-line bracket been reached?
1520
bool ASFormatter::isOneLineBlockReached() const
1522
bool isInComment = false;
1523
bool isInQuote = false;
1524
int bracketCount = 1;
1525
int currentLineLength = currentLine.length();
1526
char quoteChar = ' ';
1528
for (int i = charNum + 1; i < currentLineLength; ++i)
1530
char ch = currentLine[i];
1534
if (currentLine.compare(i, 2, "*/") == 0)
1536
isInComment = false;
1550
if (ch == quoteChar)
1555
if (ch == '"' || ch == '\'')
1562
if (currentLine.compare(i, 2, "//") == 0)
1565
if (currentLine.compare(i, 2, "/*") == 0)
1577
if (bracketCount == 0)
1585
* check if one of a set of headers has been reached in the
1586
* current position of the current line.
1588
* @return a pointer to the found header. Or a NULL if no header has been reached.
1589
* @param headers a vector of headers.
1590
* @param checkBoundry
1592
const string *ASFormatter::findHeader(const vector<const string*> &headers, bool checkBoundry)
1594
return ASBeautifier::findHeader(currentLine, charNum, headers, checkBoundry);
1598
* check if a line begins with the specified character
1599
* i.e. if the current line begins with a open bracket.
1601
* @return true or false
1603
bool ASFormatter::lineBeginsWith(char charToCheck) const
1605
bool beginsWith = false;
1606
size_t i = currentLine.find_first_not_of(" \t");
1608
if (i != string::npos)
1609
if (currentLine[i] == charToCheck && (int) i == charNum)
1616
* adjust comment position because of adding or deleting spaces
1617
* the spaces are added or deleted to formattedLine
1618
* spacePadNum contains the adjustment
1620
void ASFormatter::adjustComments(void)
1622
assert(spacePadNum != 0);
1623
assert(currentLine.compare(charNum, 2, "//") == 0
1624
|| currentLine.compare(charNum, 2, "/*") == 0);
1627
// block comment must be closed on this line with nothing after it
1628
if (currentLine.compare(charNum, 2, "/*") == 0)
1630
size_t endNum = currentLine.find("*/", charNum + 2);
1631
if (endNum == string::npos)
1633
if (currentLine.find_first_not_of(" \t", endNum + 2) != string::npos)
1637
size_t len = formattedLine.length();
1638
// if spaces were removed, need to add spaces before the comment
1639
if (spacePadNum < 0)
1641
int adjust = -spacePadNum; // make the number positive
1642
if (formattedLine[len-1] != '\t') // don't adjust if a tab
1643
formattedLine.append(adjust, ' ');
1644
// else // comment out to avoid compiler warning
1646
// TRcomment(adjust); // trace macro
1648
// if spaces were added, need to delete spaces before the comment, if possible
1649
else if (spacePadNum > 0)
1651
int adjust = spacePadNum;
1652
if (formattedLine.find_last_not_of(' ') < len - adjust - 1
1653
&& formattedLine[len-1] != '\t') // don't adjust a tab
1654
formattedLine.resize(len - adjust);
1655
// the following are commented out to avoid a Borland compiler warning
1658
TRcomment(-adjust); // trace macro
1663
* append the current bracket inside the end of line comments
1664
* currentChar contains the bracket, it will be appended to formattedLine
1665
* formattedLineCommentNum is the comment location on formattedLine
1667
void ASFormatter::appendCharInsideComments(void)
1669
if (formattedLineCommentNum == string::npos // does the comment start on the previous line?
1670
|| isBeforeComment()) // does a comment follow on this line?
1672
appendCurrentChar(true); // don't attach
1675
assert(formattedLine.compare(formattedLineCommentNum, 2, "//") == 0
1676
|| formattedLine.compare(formattedLineCommentNum, 2, "/*") == 0);
1678
// find the previous non space char
1679
size_t end = formattedLineCommentNum;
1680
size_t beg = formattedLine.find_last_not_of(" \t", end-1);
1681
if (beg == string::npos) // is the previous line comment only?
1683
appendCurrentChar(true); // don't attach
1688
// insert the bracket
1689
if (end - beg < 3) // is there room to insert?
1690
formattedLine.insert(beg, 3-end+beg, ' ');
1691
if (formattedLine[beg] == '\t') // don't pad with a tab
1692
formattedLine.insert(beg, 1, ' ');
1693
formattedLine[beg+1] = currentChar;
1697
* add or remove space padding to operators
1698
* currentChar contains the paren
1699
* the operators and necessary padding will be appended to formattedLine
1700
* the calling function should have a continue statement after calling this method
1702
* @param *newOperator the operator to be padded
1704
void ASFormatter::padOperators(const string *newOperator)
1706
assert (shouldPadOperators);
1707
assert(newOperator != NULL);
1709
bool shouldPad = (newOperator != &AS_COLON_COLON
1710
&& newOperator != &AS_PAREN_PAREN
1711
&& newOperator != &AS_BLPAREN_BLPAREN
1712
&& newOperator != &AS_PLUS_PLUS
1713
&& newOperator != &AS_MINUS_MINUS
1714
&& newOperator != &AS_NOT
1715
&& newOperator != &AS_BIT_NOT
1716
&& newOperator != &AS_ARROW
1717
&& newOperator != &AS_OPERATOR
1718
&& newOperator != &AS_RETURN
1719
&& !(newOperator == &AS_MINUS && isInExponent())
1720
&& !(newOperator == &AS_MINUS // check for negative number
1721
&& (previousNonWSChar == '('
1722
|| previousNonWSChar == '='
1723
|| previousNonWSChar == ','))
1724
&& !(newOperator == &AS_PLUS && isInExponent())
1725
&& previousOperator != &AS_OPERATOR
1726
&& !((newOperator == &AS_MULT || newOperator == &AS_BIT_AND)
1727
&& isPointerOrReference())
1728
&& !(newOperator == &AS_MULT
1729
&& (previousNonWSChar == '.'
1730
|| previousNonWSChar == '>')) // check for ->
1731
&& !((isInTemplate || isCharImmediatelyPostTemplate)
1732
&& (newOperator == &AS_LS || newOperator == &AS_GR))
1734
// pad before operator
1737
&& !(newOperator == &AS_COLON && !foundQuestionMark)
1738
&& newOperator != &AS_SEMICOLON
1739
&& newOperator != &AS_COMMA)
1741
appendSequence(*newOperator);
1742
goForward(newOperator->length() - 1);
1744
// since this block handles '()' and '[]',
1745
// the parenStack must be updated here accordingly!
1746
if (newOperator == &AS_PAREN_PAREN
1747
|| newOperator == &AS_BLPAREN_BLPAREN)
1748
parenStack->back()--;
1750
currentChar = (*newOperator)[newOperator->length() - 1];
1751
// pad after operator
1752
// but do not pad after a '-' that is a unary-minus.
1755
&& !isBeforeComment()
1756
&& !(newOperator == &AS_MINUS && isUnaryMinus())
1757
&& !(currentLine.compare(charNum + 1, 1, ";") == 0)
1758
&& !(currentLine.compare(charNum + 1, 2, "::") == 0))
1761
previousOperator = newOperator;
1766
* add or remove space padding to parens
1767
* currentChar contains the paren
1768
* the parens and necessary padding will be appended to formattedLine
1769
* the calling function should have a continue statement after calling this method
1771
void ASFormatter::padParens(void)
1773
assert(shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens);
1774
assert (currentChar == '(' || currentChar == ')');
1776
if (currentChar == '(')
1778
int spacesOutsideToDelete = formattedLine.length() - 1;
1779
int spacesInsideToDelete = 0;
1781
// compute spaces outside the opening paren to delete
1782
if (shouldUnPadParens)
1784
char lastChar = ' ';
1785
bool prevIsParenHeader = false;
1786
size_t i = formattedLine.find_last_not_of(" \t");
1787
if (i != string::npos)
1790
spacesOutsideToDelete -= i;
1791
lastChar = formattedLine[i];
1792
// was last word a paren header?
1793
int start; // start of the previous word
1794
for (start = i; start > 0; start--)
1796
if (isLegalNameChar(formattedLine[start]) || formattedLine[start] == '*')
1801
string prevWord = formattedLine.substr(start, end-start+1);
1802
// if previous word is a header, it will be a paren header
1803
const string *prevWordH = ASBeautifier::findHeader(formattedLine, start, headers);
1804
if (prevWordH != NULL)
1806
prevIsParenHeader = true;
1807
TRxtra(*prevWordH); // trace macro
1809
else if (prevWord == "return" // don't unpad return statements
1810
|| prevWord == "*") // don't unpad multiply or pointer
1812
prevIsParenHeader = true;
1813
TRxtra(prevWord); // trace macro
1815
// don't unpad variables
1816
else if (prevWord == "bool"
1817
|| prevWord == "int"
1818
|| prevWord == "void"
1819
|| prevWord == "void*"
1820
|| (prevWord.length() >= 6 // check end of word for _t
1821
&& prevWord.compare(prevWord.length()-2, 2, "_t") == 0)
1822
|| prevWord == "BOOL"
1823
|| prevWord == "DWORD"
1824
|| prevWord == "HWND"
1825
|| prevWord == "INT"
1826
|| prevWord == "LPSTR"
1827
|| prevWord == "VOID"
1828
|| prevWord == "LPVOID"
1831
prevIsParenHeader = true;
1832
TRxtra(prevWord); // trace macro
1835
// do not unpad operators, but leave them if already padded
1836
if (shouldPadParensOutside || prevIsParenHeader)
1837
spacesOutsideToDelete--;
1838
else if (lastChar == '|' // check for ||
1839
|| lastChar == '&' // check for &&
1841
|| (lastChar == '>' && !foundCastOperator)
1849
|| (lastChar == '*' && isInPotentialCalculation)
1852
spacesOutsideToDelete--;
1854
if (spacesOutsideToDelete > 0)
1856
formattedLine.erase(i + 1, spacesOutsideToDelete);
1857
spacePadNum -= spacesOutsideToDelete;
1861
// pad open paren outside
1862
char peekedCharOutside = peekNextChar();
1863
if (shouldPadParensOutside)
1864
if (!(currentChar == '(' && peekedCharOutside == ')'))
1867
appendCurrentChar();
1869
// unpad open paren inside
1870
if (shouldUnPadParens)
1872
size_t j = currentLine.find_first_not_of(" \t", charNum + 1);
1873
if (j != string::npos)
1874
spacesInsideToDelete = j - charNum - 1;
1875
if (shouldPadParensInside)
1876
spacesInsideToDelete--;
1877
if (spacesInsideToDelete > 0)
1879
currentLine.erase(charNum + 1, spacesInsideToDelete);
1880
spacePadNum -= spacesInsideToDelete;
1884
// pad open paren inside
1885
char peekedCharInside = peekNextChar();
1886
if (shouldPadParensInside)
1887
if (!(currentChar == '(' && peekedCharInside == ')'))
1890
TRunpad('(', spacesOutsideToDelete, spacesInsideToDelete); // trace macro
1892
else if (currentChar == ')' /*|| currentChar == ']'*/)
1894
int spacesOutsideToDelete = 0;
1895
int spacesInsideToDelete = formattedLine.length();
1897
// unpad close paren inside
1898
if (shouldUnPadParens)
1900
size_t i = formattedLine.find_last_not_of(" \t");
1901
if (i != string::npos)
1902
spacesInsideToDelete = formattedLine.length() - 1 - i;
1903
if (shouldPadParensInside)
1904
spacesInsideToDelete--;
1905
if (spacesInsideToDelete > 0)
1907
formattedLine.erase(i + 1, spacesInsideToDelete);
1908
spacePadNum -= spacesInsideToDelete;
1912
// pad close paren inside
1913
if (shouldPadParensInside)
1914
if (!(previousChar == '(' && currentChar == ')'))
1917
appendCurrentChar();
1919
// unpad close paren outside
1920
if (shouldUnPadParens)
1922
// may have end of line comments
1923
size_t j = currentLine.find_first_not_of(" \t", charNum + 1);
1924
if (j != string::npos)
1925
if (currentLine[j] == '[' || currentLine[j] == ']')
1926
spacesOutsideToDelete = j - charNum - 1;
1927
if (shouldPadParensOutside)
1928
spacesOutsideToDelete--;
1929
// spacesOutsideToDelete--; // always leave 1 space
1931
if (spacesOutsideToDelete > 0)
1933
currentLine.erase(charNum + 1, spacesOutsideToDelete);
1934
spacePadNum -= spacesOutsideToDelete;
1938
// pad close paren outside
1939
char peekedCharOutside = peekNextChar();
1940
if (shouldPadParensOutside)
1941
if (peekedCharOutside != ';'
1942
&& peekedCharOutside != ','
1943
&& peekedCharOutside != '.'
1944
&& peekedCharOutside != '-') // check for ->
1945
// && !(currentChar == ']' && peekedCharOutside == '['))
1948
TRunpad(')', spacesInsideToDelete, 0 /*spacesOutsideToDelete*/); // trace macro
1954
* format brackets as attached or broken
1955
* currentChar contains the bracket
1956
* the brackets will be appended to the current formattedLine or a new formattedLine as necessary
1957
* the calling function should have a continue statement after calling this method
1959
* @param bracketType the type of bracket to be formatted.
1961
void ASFormatter::formatBrackets(BracketType bracketType)
1963
assert(!IS_A(bracketType, ARRAY_TYPE));
1964
assert (currentChar == '{' || currentChar == '}');
1966
if (currentChar == '{')
1968
parenStack->push_back(0);
1970
else if (currentChar == '}')
1972
if (!parenStack->empty())
1974
parenStack->pop_back();
1978
if (currentChar == '{')
1980
bool bdacBreak = false;
1981
// should a Linux bracket be broken?
1982
if (bracketFormatMode == BDAC_MODE)
1984
// always break a class
1985
if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], CLASS_TYPE))
1987
// break a namespace and the first bracket if a function
1988
else if (bracketTypeStack->size() <= 2)
1990
if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], NAMESPACE_TYPE)
1991
|| IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], COMMAND_TYPE))
1994
// break the first bracket after a namespace if a function
1995
else if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], NAMESPACE_TYPE))
1997
if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], COMMAND_TYPE))
2000
// if not C style then break the first bracket after a class if a function
2001
else if (!ASBeautifier::isCStyle)
2003
if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], CLASS_TYPE)
2004
&& IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], COMMAND_TYPE))
2008
if (bracketFormatMode == ATTACH_MODE
2009
|| (bracketFormatMode == BDAC_MODE && !bdacBreak))
2011
// are there comments before the bracket?
2012
if (isCharImmediatelyPostComment || isCharImmediatelyPostLineComment)
2014
if ((shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE))
2015
&& peekNextChar() != '}')
2016
appendCharInsideComments();
2018
appendCurrentChar(true); // don't attach
2020
else if (previousCommandChar == '{'
2021
|| previousCommandChar == '}'
2022
|| previousCommandChar == ';') // '}' , ';' chars added for proper handling of '{' immediately after a '}' or ';'
2024
appendCurrentChar(true); // don't attach
2028
size_t firstChar = formattedLine.find_first_not_of(" \t");
2029
if (firstChar == string::npos) // if a blank line preceeds this
2030
appendCurrentChar(true); // don't attach
2031
else if (shouldBreakOneLineBlocks
2032
|| !IS_A(bracketType, SINGLE_LINE_TYPE)
2033
|| peekNextChar() == '}')
2036
appendCurrentChar(false); // OK to attach
2039
appendCurrentChar(true); // don't attach
2042
else if (bracketFormatMode == BREAK_MODE
2043
|| (bracketFormatMode == BDAC_MODE && bdacBreak))
2045
if (isBeforeComment())
2047
// do not break unless comment is at line end
2048
if (isBeforeLineEndComment(charNum))
2050
currentChar = ' '; // remove bracket from current line
2051
appendOpeningBracket = true; // append bracket to following line
2054
else if (!IS_A(bracketType, SINGLE_LINE_TYPE))
2056
else if (shouldBreakOneLineBlocks && peekNextChar() != '}')
2059
appendCurrentChar();
2061
else if (bracketFormatMode == NONE_MODE)
2063
if (lineBeginsWith('{')) // is opening bracket broken?
2064
appendCurrentChar(true);
2066
appendCurrentChar(false);
2069
else if (currentChar == '}')
2071
// mark state of immediately after empty block
2072
// this state will be used for locating brackets that appear immedately AFTER an empty block (e.g. '{} \n}').
2073
if (previousCommandChar == '{')
2074
isImmediatelyPostEmptyBlock = true;
2076
if ((!(previousCommandChar == '{' && isPreviousBracketBlockRelated)) // this '{' does not close an empty block
2077
&& (shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE)) // astyle is allowed to break on line blocks
2078
&& (!(bracketFormatMode == NONE_MODE && IS_A(bracketType, SINGLE_LINE_TYPE)))
2079
&& !isImmediatelyPostEmptyBlock) // this '}' does not immediately follow an empty block
2082
appendCurrentChar();
2086
if (!isCharImmediatelyPostComment
2087
&& !bracketFormatMode == NONE_MODE
2088
&& !isImmediatelyPostEmptyBlock)
2089
isInLineBreak = false;
2091
appendCurrentChar();
2093
//if (!bracketFormatMode == NONE_MODE)
2094
// if ((shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE))
2095
// && !(currentChar == '}' && peekNextChar() == ';')) // fixes }; placed on separate lines
2096
// shouldBreakLineAfterComments = true;
2099
if (shouldBreakBlocks)
2101
isAppendPostBlockEmptyLineRequested = true;
2108
* format array brackets as attached or broken
2109
* determine if the brackets can have an inStatement indent
2110
* currentChar contains the bracket
2111
* the brackets will be appended to the current formattedLine or a new formattedLine as necessary
2112
* the calling function should have a continue statement after calling this method
2114
* @param bracketType the type of bracket to be formatted, must be an ARRAY_TYPE.
2115
* @param isOpeningArrayBracket indicates if this is the opening bracket for the array block.
2117
void ASFormatter::formatArrayBrackets(BracketType bracketType, bool isOpeningArrayBracket)
2119
assert(IS_A(bracketType, ARRAY_TYPE));
2120
assert (currentChar == '{' || currentChar == '}');
2122
if (currentChar == '{')
2124
// is this the first opening bracket in the array?
2125
if (isOpeningArrayBracket)
2127
if (bracketFormatMode == ATTACH_MODE || bracketFormatMode == BDAC_MODE)
2129
// don't attach to a preprocessor directive
2130
if (isImmediatelyPostPreprocessor)
2131
appendCurrentChar(true); // don't attach
2132
// are there comments before the bracket?
2133
else if (isCharImmediatelyPostComment || isCharImmediatelyPostLineComment)
2135
appendCharInsideComments();
2139
// if bracket is broken or not an assignment
2140
if (lineBeginsWith('{') || previousNonWSChar != '=')
2142
appendCurrentChar(false); // OK to attach
2145
else if (bracketFormatMode == BREAK_MODE)
2147
if (isWhiteSpace(peekNextChar()))
2149
else if (isBeforeComment())
2151
// do not break unless comment is at line end
2152
if (isBeforeLineEndComment(charNum))
2154
currentChar = ' '; // remove bracket from current line
2155
appendOpeningBracket = true; // append bracket to following line
2158
appendCurrentChar();
2160
else if (bracketFormatMode == NONE_MODE)
2162
if (lineBeginsWith('{')) // is opening bracket broken?
2163
appendCurrentChar();
2165
appendCurrentChar(false);
2169
appendCurrentChar(); // not the first opening bracket - don't change
2171
// if an opening bracket ends the line there will be no inStatement indent
2172
char nextChar = peekNextChar();
2173
if (isWhiteSpace(nextChar)
2174
|| isBeforeLineEndComment(charNum)
2176
isNonInStatementArray = true;
2177
if (isNonInStatementArray)
2183
else if (currentChar == '}')
2185
// does this close the first opening bracket in the array?
2186
if (isOpeningArrayBracket && !IS_A(bracketType, SINGLE_LINE_TYPE) )
2189
appendCurrentChar();
2192
appendCurrentChar();
2197
} // end namespace astyle