~ubuntu-branches/ubuntu/utopic/qgis/utopic

« back to all changes in this revision

Viewing changes to src/astyle/ASFormatter.cpp

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2012-04-24 15:12:20 UTC
  • mfrom: (3.1.9 sid)
  • Revision ID: package-import@ubuntu.com-20120424151220-r88g00af5fpn5fc3
Tags: 1.7.4+1.7.5~20120320-1
The "Sometimes they come back" release.

* Branching from Qgis tree and adapting to current Debian Policy and
  standards. The target tree is currently set to release-1.7.
  (closes: #661491, #606304, #615683, #616182, #600308)
* Policy bumped to 3.9.3.
* Moving to debhelper compatibility level 9.
* Source format is now 3.0 with quilt support.
* Merged with 2bf42287 upstream git snapshot.
* Migrated to dh_python2 instead of python-central.
  (closes: #617048)
* Snapshot in qgis.org release-1.7: c936d031
* Added an automagic creation of a lintian override for sqlite embedding.
  This is required for uploading currently.
* Added missing ${misc:Depends} to make lintian happy.
* Copyright notes updated and debian/copyright moved to format 1.0.
* More licenses notices now reported in debian/copyright. Thanks ftpmasters.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
2
 *
 
3
 *   ASFormatter.cpp
 
4
 *
 
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
 
8
 *
 
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
 
14
 *   version.
 
15
 *
 
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.
 
20
 *
 
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.
 
25
 *
 
26
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
27
 */
 
28
 
 
29
#include "astyle.h"
 
30
 
 
31
#include <algorithm>
 
32
#include <fstream>
 
33
#include <iostream>
 
34
 
 
35
// can trace only if NDEBUG is not defined
 
36
#ifndef NDEBUG
 
37
// #define TRACEunpad
 
38
// #define TRACEcomment
 
39
// #define TRACEheader
 
40
// #define TRACEbracket
 
41
// #define TRACEarray
 
42
#if defined(TRACEunpad) || defined(TRACEcomment) || defined(TRACEheader) \
 
43
|| defined(TRACEbracket) || defined(TRACEarray)
 
44
ofstream *traceOutF;
 
45
#define TRACEF
 
46
#endif
 
47
#endif
 
48
 
 
49
#ifdef TRACEunpad
 
50
#define TRunpad(a,b,c)  if(b > 0 || c > 0) *traceOutF << traceLineNumber << " " << b << a << c << endl
 
51
#else
 
52
#define TRunpad(a,b,c)  ((void)0)
 
53
#endif
 
54
 
 
55
#ifdef TRACEcomment
 
56
#define TRcomment(a)    *traceOutF << traceLineNumber << " " << a << endl
 
57
#else
 
58
#define TRcomment(a)    ((void)0)
 
59
#endif
 
60
 
 
61
#ifdef TRACEheader
 
62
#define TRxtra(a)       *traceOutF << traceLineNumber << " " << a << endl
 
63
#else
 
64
#define TRxtra(a)    ((void)0)
 
65
#endif
 
66
 
 
67
#ifdef TRACEbracket
 
68
#define TRbracket(a)       *traceOutF << traceLineNumber << " " << a << endl
 
69
#else
 
70
#define TRbracket(a)    ((void)0)
 
71
#endif
 
72
 
 
73
#ifdef TRACEarray
 
74
#define TRarray(a)      *traceOutF << traceLineNumber << " " << a << endl
 
75
#else
 
76
#define TRarray(a)      ((void)0)
 
77
#endif
 
78
 
 
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))
 
82
 
 
83
using namespace std;
 
84
 
 
85
namespace astyle
 
86
{
 
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;
 
94
 
 
95
/**
 
96
 * Constructor of ASFormatter
 
97
 */
 
98
ASFormatter::ASFormatter()
 
99
{
 
100
        preBracketHeaderStack = NULL;
 
101
        bracketTypeStack = NULL;
 
102
        parenStack = 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;
 
117
#ifdef TRACEF
 
118
        // create a trace text file
 
119
        string traceFileName = "tracef.txt";
 
120
        char* env = getenv("HOME");
 
121
        if (env != NULL)
 
122
                traceFileName = string(env) + string("/tracef.txt");
 
123
        else
 
124
        {
 
125
                env = getenv("USERPROFILE");
 
126
                if (env != NULL)
 
127
                        traceFileName = string(env) + string("\\My Documents\\tracef.txt");
 
128
                else
 
129
                {
 
130
                        cout << "\nCould not open tracef.txt\n" << endl;
 
131
                        exit(1);
 
132
                }
 
133
        }
 
134
        traceOutF = new ofstream(traceFileName.c_str());
 
135
#endif
 
136
}
 
137
 
 
138
/**
 
139
 * Destructor of ASFormatter
 
140
 */
 
141
ASFormatter::~ASFormatter()
 
142
{
 
143
        DELETE_CONTAINER(preBracketHeaderStack);
 
144
#ifdef TRACEF
 
145
        delete traceOutF;
 
146
#endif
 
147
}
 
148
 
 
149
/**
 
150
 * initialization of static data of ASFormatter.
 
151
 */
 
152
void ASFormatter::staticInit()
 
153
{
 
154
        static int formatterFileType = 9;      // initialized with an invalid type
 
155
 
 
156
        if (fileType == formatterFileType)     // don't build unless necessary
 
157
                return;
 
158
 
 
159
        formatterFileType = fileType;
 
160
 
 
161
        headers.clear();
 
162
        nonParenHeaders.clear();
 
163
        assignmentOperators.clear();
 
164
        operators.clear();
 
165
        preDefinitionHeaders.clear();
 
166
        preCommandHeaders.clear();
 
167
        castOperators.clear();
 
168
 
 
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);
 
176
}
 
177
 
 
178
/**
 
179
 * initialize the ASFormatter.
 
180
 *
 
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
 
186
 * deleted elsewhere.
 
187
 *
 
188
 * @param iter     a pointer to the DYNAMICALLY CREATED ASSourceIterator object.
 
189
 */
 
190
void ASFormatter::init(ASSourceIterator *si)
 
191
{
 
192
        staticInit();
 
193
 
 
194
        ASBeautifier::init(si);
 
195
        ASEnhancer::init(getIndentLength(),
 
196
                         getIndentString(),
 
197
                         getCStyle(),
 
198
                         getJavaStyle(),
 
199
                         getSharpStyle(),
 
200
                         getCaseIndent(),
 
201
                         getEmptyLineFill());
 
202
        sourceIterator = si;
 
203
 
 
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
 
209
 
 
210
        currentHeader = NULL;
 
211
        currentLine = string("");
 
212
        readyFormattedLine = string("");
 
213
        formattedLine = "";
 
214
        currentChar = ' ';
 
215
        previousChar = ' ';
 
216
        previousCommandChar = ' ';
 
217
        previousNonWSChar = ' ';
 
218
        quoteChar = '"';
 
219
        charNum = 0;
 
220
        spacePadNum = 0;
 
221
        previousReadyFormattedLineLength = string::npos;
 
222
        templateDepth = 0;
 
223
        traceLineNumber = 0;
 
224
        previousBracketType = NULL_TYPE;
 
225
        previousOperator = NULL;
 
226
 
 
227
        isVirgin = true;
 
228
        isInLineComment = false;
 
229
        isInComment = false;
 
230
        isInPreprocessor = false;
 
231
        doesLineStartComment = false;
 
232
        isInQuote = 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;
 
246
        isLineReady = false;
 
247
        isPreviousBracketBlockRelated = true;
 
248
        isInPotentialCalculation = false;
 
249
        shouldReparseCurrentChar = false;
 
250
        passedSemicolon = false;
 
251
        passedColon = false;
 
252
        isInTemplate = false;
 
253
        isInBlParen = false;
 
254
//      shouldBreakLineAfterComments = false;
 
255
        isImmediatelyPostComment = false;
 
256
        isImmediatelyPostLineComment = false;
 
257
        isImmediatelyPostEmptyBlock = false;
 
258
        isImmediatelyPostPreprocessor = false;
 
259
 
 
260
        isPrependPostBlockEmptyLineRequested = false;
 
261
        isAppendPostBlockEmptyLineRequested = false;
 
262
        prependEmptyLine = false;
 
263
        appendOpeningBracket = false;
 
264
 
 
265
        foundClosingHeader = false;
 
266
        previousReadyFormattedLineLength = 0;
 
267
 
 
268
        isImmediatelyPostHeader = false;
 
269
        isInHeader = false;
 
270
        isInCase = false;
 
271
#ifdef TRACEF
 
272
        // traceFileName will be empty if ASTYLE_LIB is defined
 
273
        if (traceFileName.empty())
 
274
                *traceOutF << "new file" << endl;
 
275
        else
 
276
                *traceOutF << traceFileName << endl;
 
277
#endif
 
278
}
 
279
 
 
280
/**
 
281
 * get the next formatted line.
 
282
 *
 
283
 * @return    formatted line.
 
284
 */
 
285
 
 
286
string ASFormatter::nextLine()
 
287
{
 
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;
 
297
        traceLineNumber++;
 
298
 
 
299
        while (!isLineReady)
 
300
        {
 
301
                if (shouldReparseCurrentChar)
 
302
                        shouldReparseCurrentChar = false;
 
303
                else if (!getNextChar())
 
304
                {
 
305
                        breakLine();
 
306
                        return beautify(readyFormattedLine);
 
307
                }
 
308
                else // stuff to do when reading a new character...
 
309
                {
 
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;
 
316
                }
 
317
 
 
318
//              if (inLineNumber >= 1159)
 
319
//                      int x = 1;
 
320
 
 
321
                if (isInLineComment)
 
322
                {
 
323
                        appendCurrentChar();
 
324
 
 
325
                        // explicitly break a line when a line comment's end is found.
 
326
                        if (charNum + 1 == (int) currentLine.length())
 
327
                        {
 
328
                                isInLineBreak = true;
 
329
                                isInLineComment = false;
 
330
                                isImmediatelyPostLineComment = true;
 
331
                                currentChar = 0;  //make sure it is a neutral char.
 
332
                        }
 
333
                        continue;
 
334
                }
 
335
                else if (isInComment)
 
336
                {
 
337
                        if (isSequenceReached("*/"))
 
338
                        {
 
339
                                isInComment = false;
 
340
                                isImmediatelyPostComment = true;
 
341
                                appendSequence(AS_CLOSE_COMMENT);
 
342
                                goForward(1);
 
343
                        }
 
344
                        else
 
345
                                appendCurrentChar();
 
346
 
 
347
                        continue;
 
348
                }
 
349
 
 
350
                // not in line comment or comment
 
351
 
 
352
                else if (isInQuote)
 
353
                {
 
354
                        if (isSpecialChar)
 
355
                        {
 
356
                                isSpecialChar = false;
 
357
                        }
 
358
                        else if (currentChar == '\\' && !isInVerbatimQuote)
 
359
                        {
 
360
                                if (peekNextChar() == ' ')                              // is this '\' at end of line
 
361
                                        haveLineContinuationChar = true;
 
362
                                else
 
363
                                        isSpecialChar = true;
 
364
                        }
 
365
                        else if (isInVerbatimQuote && currentChar == '"' )
 
366
                        {
 
367
                                if (peekNextChar() == '"')                              // check consecutive quotes
 
368
                                {
 
369
                                        appendSequence("\"\"");
 
370
                                        goForward(1);
 
371
                                        continue;
 
372
                                }
 
373
                                else
 
374
                                {
 
375
                                        isInQuote = false;
 
376
                                        isInVerbatimQuote = false;
 
377
                                }
 
378
                        }
 
379
                        else if (quoteChar == currentChar)
 
380
                        {
 
381
                                isInQuote = false;
 
382
                        }
 
383
 
 
384
                        appendCurrentChar();
 
385
                        continue;
 
386
                }
 
387
 
 
388
                if (isSequenceReached("//"))
 
389
                {
 
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)
 
395
                        {
 
396
                                if (charNum == 0)
 
397
                                        lineCommentNoIndent = true;
 
398
                                else if (charNum == 1 && currentLine[0] == ' ')
 
399
                                        lineCommentNoIndent = true;
 
400
                        }
 
401
                        // move comment if spaces were added or deleted
 
402
                        if (lineCommentNoIndent == false && spacePadNum != 0)
 
403
                                adjustComments();
 
404
                        formattedLineCommentNum = formattedLine.length();
 
405
                        appendSequence(AS_OPEN_LINE_COMMENT);
 
406
                        goForward(1);
 
407
                        // explicitly break a line when a line comment's end is found.
 
408
                        if (charNum + 1 == (int) currentLine.length())
 
409
                        {
 
410
                                isInLineBreak = true;
 
411
                                isInLineComment = false;
 
412
                                isImmediatelyPostLineComment = true;
 
413
                                currentChar = 0;  //make sure it is a neutral char.
 
414
                        }
 
415
                        continue;
 
416
                }
 
417
                else if (isSequenceReached("/*"))
 
418
                {
 
419
                        isInComment = true;
 
420
                        if (spacePadNum != 0)
 
421
                                adjustComments();
 
422
                        formattedLineCommentNum = formattedLine.length();
 
423
                        appendSequence(AS_OPEN_COMMENT);
 
424
                        goForward(1);
 
425
                        continue;
 
426
                }
 
427
                else if (currentChar == '"' || currentChar == '\'')
 
428
                {
 
429
                        isInQuote = true;
 
430
                        if (isSharpStyle && previousChar == '@')
 
431
                                isInVerbatimQuote = true;
 
432
                        quoteChar = currentChar;
 
433
                        appendCurrentChar();
 
434
                        continue;
 
435
                }
 
436
 
 
437
                // handle white space - needed to simplify the rest.
 
438
                if (isWhiteSpace(currentChar) || isInPreprocessor)
 
439
                {
 
440
                        appendCurrentChar();
 
441
                        continue;
 
442
                }
 
443
 
 
444
                /* not in MIDDLE of quote or comment or white-space of any type ... */
 
445
 
 
446
                // need to reset 'previous' chars if appending a bracket
 
447
                if (appendOpeningBracket)
 
448
                        previousCommandChar = previousNonWSChar = previousChar = '{';
 
449
 
 
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 == '#')
 
454
                {
 
455
                        isInPreprocessor = true;
 
456
                        appendCurrentChar();
 
457
                        continue;
 
458
                }
 
459
 
 
460
                /* not in preprocessor ... */
 
461
 
 
462
                if (isImmediatelyPostComment)
 
463
                {
 
464
                        isImmediatelyPostComment = false;
 
465
                        isCharImmediatelyPostComment = true;
 
466
                }
 
467
 
 
468
                if (isImmediatelyPostLineComment)
 
469
                {
 
470
                        isImmediatelyPostLineComment = false;
 
471
                        isCharImmediatelyPostLineComment = true;
 
472
                }
 
473
 
 
474
//              if (shouldBreakLineAfterComments)
 
475
//              {
 
476
//                      shouldBreakLineAfterComments = false;
 
477
//                      shouldReparseCurrentChar = true;
 
478
//                      breakLine();
 
479
//                      continue;
 
480
//              }
 
481
 
 
482
                // reset isImmediatelyPostHeader information
 
483
                if (isImmediatelyPostHeader)
 
484
                {
 
485
                        isImmediatelyPostHeader = false;
 
486
 
 
487
                        // Make sure headers are broken from their succeeding blocks
 
488
                        // (e.g.
 
489
                        //     if (isFoo) DoBar();
 
490
                        //  should become
 
491
                        //     if (isFoo)
 
492
                        //         DoBar;
 
493
                        // )
 
494
                        // But treat else if() as a special case which should not be broken!
 
495
                        if (shouldBreakOneLineStatements)
 
496
                        {
 
497
                                // if may break 'else if()'s, then simply break the line
 
498
 
 
499
                                if (shouldBreakElseIfs)
 
500
                                        isInLineBreak = true;
 
501
                        }
 
502
                }
 
503
 
 
504
                if (passedSemicolon)    // need to break the formattedLine
 
505
                {
 
506
                        passedSemicolon = false;
 
507
                        if (parenStack->back() == 0 && currentChar != ';') // allow ;;
 
508
                        {
 
509
                                // does a one-line statement have ending comments?
 
510
                                if (IS_A(bracketTypeStack->back(), SINGLE_LINE_TYPE))
 
511
                                {
 
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))
 
516
                                        {
 
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();
 
523
                                                appendSpacePad();
 
524
                                                for (int i=1; i<tabCount; i++)
 
525
                                                        formattedLine.append(1, ' ');
 
526
                                                formattedLine.append(currentLine, commentStart, commentLength);
 
527
                                                currentLine.erase(commentStart, commentLength);
 
528
                                        }
 
529
                                }
 
530
                                shouldReparseCurrentChar = true;
 
531
                                isInLineBreak = true;
 
532
                                continue;
 
533
                        }
 
534
                }
 
535
 
 
536
                if (passedColon)
 
537
                {
 
538
                        passedColon = false;
 
539
                        if (parenStack->back() == 0 && !isBeforeComment())
 
540
                        {
 
541
                                shouldReparseCurrentChar = true;
 
542
                                isInLineBreak = true;
 
543
                                continue;
 
544
                        }
 
545
                }
 
546
 
 
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 == '<')
 
550
                {
 
551
                        int maxTemplateDepth = 0;
 
552
                        templateDepth = 0;
 
553
                        for (size_t i = charNum;
 
554
                                i < currentLine.length();
 
555
                                i ++)
 
556
                        {
 
557
                                char currentChar = currentLine[i];
 
558
 
 
559
                                if (currentChar == '<')
 
560
                                {
 
561
                                        templateDepth++;
 
562
                                        maxTemplateDepth++;
 
563
                                }
 
564
                                else if (currentChar == '>')
 
565
                                {
 
566
                                        templateDepth--;
 
567
                                        if (templateDepth == 0)
 
568
                                        {
 
569
                                                // this is a template!
 
570
                                                isInTemplate = true;
 
571
                                                templateDepth = maxTemplateDepth;
 
572
                                                break;
 
573
                                        }
 
574
                                }
 
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[]
 
581
                                {
 
582
                                        continue;
 
583
                                }
 
584
                                else if (!isLegalNameChar(currentChar) && !isWhiteSpace(currentChar))
 
585
                                {
 
586
                                        // this is not a template -> leave...
 
587
                                        isInTemplate = false;
 
588
                                        break;
 
589
                                }
 
590
                        }
 
591
                }
 
592
 
 
593
                // handle parenthesies
 
594
                if (currentChar == '(' || currentChar == '[' || (isInTemplate && currentChar == '<'))
 
595
                {
 
596
                        parenStack->back()++;
 
597
                        if (currentChar == '[')
 
598
                                isInBlParen = true;
 
599
                }
 
600
                else if (currentChar == ')' || currentChar == ']' || (isInTemplate && currentChar == '>'))
 
601
                {
 
602
                        parenStack->back()--;
 
603
                        if (isInTemplate && currentChar == '>')
 
604
                        {
 
605
                                templateDepth--;
 
606
                                if (templateDepth == 0)
 
607
                                {
 
608
                                        isInTemplate = false;
 
609
                                        isCharImmediatelyPostTemplate = true;
 
610
                                }
 
611
                        }
 
612
 
 
613
                        // check if this parenthesis closes a header, e.g. if (...), while (...)
 
614
                        if (isInHeader && parenStack->back() == 0)
 
615
                        {
 
616
                                isInHeader = false;
 
617
                                isImmediatelyPostHeader = true;
 
618
                        }
 
619
                        if (currentChar == ']')
 
620
                                isInBlParen = false;
 
621
                        if (currentChar == ')')
 
622
                                foundCastOperator = false;
 
623
                }
 
624
 
 
625
                // handle brackets
 
626
                if (currentChar == '{' || currentChar == '}')
 
627
                {
 
628
                        if (currentChar == '{')
 
629
                        {
 
630
                                BracketType newBracketType = getBracketType();
 
631
                                foundNamespaceHeader = false;
 
632
                                foundClassHeader = false;
 
633
                                foundPreDefinitionHeader = false;
 
634
                                foundPreCommandHeader = false;
 
635
                                isInPotentialCalculation = false;
 
636
 
 
637
                                bracketTypeStack->push_back(newBracketType);
 
638
                                preBracketHeaderStack->push_back(currentHeader);
 
639
                                currentHeader = NULL;
 
640
 
 
641
                                isPreviousBracketBlockRelated = !IS_A(newBracketType, ARRAY_TYPE);
 
642
                        }
 
643
 
 
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)
 
649
                                                     );
 
650
 
 
651
                        if (currentChar == '}')
 
652
                        {
 
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.
 
656
                                //
 
657
                                isAppendPostBlockEmptyLineRequested = false;
 
658
 
 
659
                                if (bracketTypeStack->size() > 1)
 
660
                                {
 
661
                                        previousBracketType = bracketTypeStack->back();
 
662
                                        bracketTypeStack->pop_back();
 
663
                                        isPreviousBracketBlockRelated = !IS_A(bracketType, ARRAY_TYPE);
 
664
                                }
 
665
                                else
 
666
                                {
 
667
                                        previousBracketType = NULL_TYPE;
 
668
                                        isPreviousBracketBlockRelated = false;
 
669
                                }
 
670
 
 
671
                                if (!preBracketHeaderStack->empty())
 
672
                                {
 
673
                                        currentHeader = preBracketHeaderStack->back();
 
674
                                        preBracketHeaderStack->pop_back();
 
675
                                }
 
676
                                else
 
677
                                        currentHeader = NULL;
 
678
                        }
 
679
 
 
680
                        // format brackets
 
681
                        if (IS_A(bracketType, ARRAY_TYPE))
 
682
                                formatArrayBrackets(bracketType, isOpeningArrayBracket);
 
683
                        else
 
684
                                formatBrackets(bracketType);
 
685
                        continue;
 
686
                }
 
687
 
 
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)))
 
700
                {
 
701
                        isCharImmediatelyPostOpenBlock = (previousCommandChar == '{');
 
702
                        isCharImmediatelyPostCloseBlock = (previousCommandChar == '}');
 
703
 
 
704
                        previousCommandChar = ' ';
 
705
                        isInLineBreak = true;
 
706
                }
 
707
 
 
708
                // reset block handling flags
 
709
                isImmediatelyPostEmptyBlock = false;
 
710
 
 
711
                // look for headers
 
712
                if (!isInTemplate)
 
713
                {
 
714
                        newHeader = findHeader(headers);
 
715
 
 
716
                        if (newHeader != NULL)
 
717
                        {
 
718
                                char peekChar = ASBeautifier::peekNextChar(currentLine, charNum + newHeader->length() - 1);
 
719
 
 
720
                                // is not a header if part of a definition
 
721
                                if (peekChar == ',' || peekChar == ')')
 
722
                                        newHeader = NULL;
 
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)
 
726
                                         && peekChar == ';')
 
727
                                {
 
728
                                        newHeader = NULL;
 
729
                                }
 
730
                        }
 
731
 
 
732
                        if (newHeader != NULL)
 
733
                        {
 
734
                                foundClosingHeader = false;
 
735
                                const string *previousHeader;
 
736
 
 
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;
 
745
 
 
746
                                previousHeader = currentHeader;
 
747
                                currentHeader = newHeader;
 
748
 
 
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 == '}')
 
757
                                {
 
758
                                        spacePadNum = 0;                // don't count as padding
 
759
 
 
760
                                        size_t firstChar = formattedLine.find_first_not_of(" \t");
 
761
                                        if (firstChar != string::npos)          // if a blank line does not preceed this
 
762
                                        {
 
763
                                                isInLineBreak = false;
 
764
                                                appendSpacePad();
 
765
                                        }
 
766
 
 
767
                                        if (shouldBreakBlocks)
 
768
                                                isAppendPostBlockEmptyLineRequested = false;
 
769
                                }
 
770
 
 
771
                                // If NONE bracket mode, leave closing headers as they are (e.g. 'else', 'catch')
 
772
                                if (foundClosingHeader && bracketFormatMode == NONE_MODE && previousCommandChar == '}')
 
773
                                {
 
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] == '}')
 
778
                                        {
 
779
                                                isInLineBreak = false;
 
780
                                                appendSpacePad();
 
781
                                        }
 
782
 
 
783
                                        if (shouldBreakBlocks)
 
784
                                                isAppendPostBlockEmptyLineRequested = false;
 
785
                                }
 
786
 
 
787
                                if (foundClosingHeader && bracketFormatMode == BREAK_MODE && previousCommandChar == '}')
 
788
                                        breakLine();
 
789
 
 
790
                                // check if the found header is non-paren header
 
791
                                isNonParenHeader = (find(nonParenHeaders.begin(), nonParenHeaders.end(),
 
792
                                                         newHeader) != nonParenHeaders.end());
 
793
 
 
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]))
 
801
                                        appendSpacePad();
 
802
 
 
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))
 
808
                                {
 
809
                                        isInHeader = true;
 
810
                                        if (isNonParenHeader)
 
811
                                        {
 
812
                                                isImmediatelyPostHeader = true;
 
813
                                                isInHeader = false;
 
814
                                        }
 
815
                                }
 
816
 
 
817
                                if (currentHeader == &AS_IF && previousHeader == &AS_ELSE)
 
818
                                        isInLineBreak = false;
 
819
 
 
820
                                if (shouldBreakBlocks)
 
821
                                {
 
822
                                        if (previousHeader == NULL
 
823
                                                && !foundClosingHeader
 
824
                                                && !isCharImmediatelyPostOpenBlock)
 
825
                                        {
 
826
                                                isPrependPostBlockEmptyLineRequested = true;
 
827
                                        }
 
828
 
 
829
                                        if (currentHeader == &AS_ELSE
 
830
                                                || currentHeader == &AS_CATCH
 
831
                                                || currentHeader == &AS_FINALLY
 
832
                                                || foundClosingHeader)
 
833
                                        {
 
834
                                                isPrependPostBlockEmptyLineRequested = false;
 
835
                                        }
 
836
 
 
837
                                        if (shouldBreakClosingHeaderBlocks
 
838
                                                &&  isCharImmediatelyPostCloseBlock)
 
839
                                        {
 
840
                                                isPrependPostBlockEmptyLineRequested = true;
 
841
                                        }
 
842
 
 
843
                                }
 
844
 
 
845
                                continue;
 
846
                        }
 
847
                        else if ((newHeader = findHeader(preDefinitionHeaders)) != NULL
 
848
                                 && parenStack->back() == 0)
 
849
                        {
 
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);
 
857
 
 
858
                                if (shouldBreakBlocks)
 
859
                                        isPrependPostBlockEmptyLineRequested = true;
 
860
 
 
861
                                continue;
 
862
                        }
 
863
                        else if ((newHeader = findHeader(preCommandHeaders)) != NULL)
 
864
                        {
 
865
                                if (isJavaStyle
 
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);
 
871
 
 
872
                                continue;
 
873
                        }
 
874
                        else if ((newHeader = findHeader(castOperators)) != NULL)
 
875
                        {
 
876
                                foundCastOperator = true;
 
877
                                appendSequence(*newHeader);
 
878
                                goForward(newHeader->length() - 1);
 
879
 
 
880
                                continue;
 
881
                        }
 
882
 
 
883
                        if (findKeyword(currentLine, charNum, "case")
 
884
                                || findKeyword(currentLine, charNum, "default"))
 
885
                                isInCase = true;
 
886
                }
 
887
 
 
888
                if (isInLineBreak)          // OK to break line here
 
889
                        breakLine();
 
890
 
 
891
                if (previousNonWSChar == '}' || currentChar == ';')
 
892
                {
 
893
                        if (shouldBreakOneLineStatements && currentChar == ';'
 
894
                                && (shouldBreakOneLineBlocks || !IS_A(bracketTypeStack->back(),  SINGLE_LINE_TYPE))
 
895
                                //&& (! bracketFormatMode == NONE_MODE)
 
896
                           )
 
897
                        {
 
898
                                passedSemicolon = true;
 
899
                        }
 
900
 
 
901
                        if (shouldBreakBlocks && currentHeader != NULL && parenStack->back() == 0)
 
902
                        {
 
903
                                isAppendPostBlockEmptyLineRequested = true;
 
904
                        }
 
905
 
 
906
                        if (currentChar != ';')
 
907
                                currentHeader = NULL;
 
908
 
 
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;
 
918
                }
 
919
 
 
920
                if (currentChar == ':' && shouldBreakOneLineStatements)
 
921
                {
 
922
                        if (isInCase
 
923
                                && previousChar != ':'                  // not part of '::'
 
924
                                && peekNextChar() != ':')               // not part of '::'
 
925
                        {
 
926
                                isInCase = false;
 
927
                                passedColon = true;
 
928
                                if (shouldBreakBlocks)
 
929
                                        isPrependPostBlockEmptyLineRequested = true;
 
930
 
 
931
                        }
 
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 '::'
 
938
                        {
 
939
                                passedColon = true;
 
940
                                if (shouldBreakBlocks)
 
941
                                        isPrependPostBlockEmptyLineRequested = true;
 
942
                        }
 
943
                }
 
944
 
 
945
                if (currentChar == '?')
 
946
                        foundQuestionMark = true;
 
947
 
 
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))
 
952
                        newHeader = &AS_GR;
 
953
 
 
954
                if (newHeader != NULL)
 
955
                {
 
956
                        if (!isInPotentialCalculation)
 
957
                        {
 
958
                                if (find(assignmentOperators.begin(), assignmentOperators.end(), newHeader)
 
959
                                        != assignmentOperators.end())
 
960
                                {
 
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 == '&'));
 
968
                                }
 
969
                        }
 
970
                }
 
971
                else
 
972
                {
 
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;
 
977
                }
 
978
 
 
979
                if (shouldPadOperators && newHeader != NULL)
 
980
                {
 
981
                        padOperators(newHeader);
 
982
                        continue;
 
983
                }
 
984
 
 
985
                if ((shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens)
 
986
                        && (currentChar == '(' || currentChar == ')'))
 
987
                {
 
988
                        padParens();
 
989
                        continue;
 
990
                }
 
991
 
 
992
                appendCurrentChar();
 
993
        }   // end of while loop  *  end of while loop  *  end of while loop  *  end of while loop
 
994
 
 
995
        // return a beautified (i.e. correctly indented) line.
 
996
 
 
997
        string beautifiedLine;
 
998
        size_t readyFormattedLineLength = trim(readyFormattedLine).length();
 
999
 
 
1000
        if (prependEmptyLine                // prepend a blank line before this formatted line
 
1001
                && readyFormattedLineLength > 0
 
1002
                && previousReadyFormattedLineLength > 0)
 
1003
        {
 
1004
                isLineReady = true;             // signal a waiting readyFormattedLine
 
1005
                beautifiedLine = beautify("");
 
1006
                previousReadyFormattedLineLength = 0;
 
1007
        }
 
1008
        else                                                            // format the current formatted line
 
1009
        {
 
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
 
1016
                {
 
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;
 
1023
                }
 
1024
        }
 
1025
 
 
1026
        prependEmptyLine = false;
 
1027
        enhance(beautifiedLine);                // call the enhancer function
 
1028
        return beautifiedLine;
 
1029
}
 
1030
 
 
1031
 
 
1032
/**
 
1033
* check if there are any indented lines ready to be read by nextLine()
 
1034
*
 
1035
* @return    are there any indented lines ready?
 
1036
*/
 
1037
bool ASFormatter::hasMoreLines() const
 
1038
{
 
1039
        return !endOfCodeReached;
 
1040
}
 
1041
 
 
1042
/**
 
1043
 * set the bracket formatting mode.
 
1044
 * options:
 
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.
 
1048
 *
 
1049
 * @param mode         the bracket formatting mode.
 
1050
 */
 
1051
void ASFormatter::setBracketFormatMode(BracketMode mode)
 
1052
{
 
1053
        bracketFormatMode = mode;
 
1054
}
 
1055
 
 
1056
/**
 
1057
 * set closing header bracket breaking mode
 
1058
 * options:
 
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.
 
1062
 *
 
1063
 * @param state         the closing header bracket breaking mode.
 
1064
 */
 
1065
void ASFormatter::setBreakClosingHeaderBracketsMode(bool state)
 
1066
{
 
1067
        shouldBreakClosingHeaderBrackets = state;
 
1068
}
 
1069
 
 
1070
/**
 
1071
 * set 'else if()' breaking mode
 
1072
 * options:
 
1073
 *    true     'else' headers will be broken from their succeeding 'if' headers.
 
1074
 *    false    'else' headers will be attached to their succeeding 'if' headers.
 
1075
 *
 
1076
 * @param state         the 'else if()' breaking mode.
 
1077
 */
 
1078
void ASFormatter::setBreakElseIfsMode(bool state)
 
1079
{
 
1080
        shouldBreakElseIfs = state;
 
1081
}
 
1082
 
 
1083
/**
 
1084
 * set operator padding mode.
 
1085
 * options:
 
1086
 *    true     statement operators will be padded with spaces around them.
 
1087
 *    false    statement operators will not be padded.
 
1088
 *
 
1089
 * @param state         the padding mode.
 
1090
 */
 
1091
void ASFormatter::setOperatorPaddingMode(bool state)
 
1092
{
 
1093
        shouldPadOperators = state;
 
1094
}
 
1095
 
 
1096
/**
 
1097
* set parenthesis outside padding mode.
 
1098
* options:
 
1099
*    true     statement parenthesiss will be padded with spaces around them.
 
1100
*    false    statement parenthesiss will not be padded.
 
1101
*
 
1102
* @param state         the padding mode.
 
1103
*/
 
1104
void ASFormatter::setParensOutsidePaddingMode(bool state)
 
1105
{
 
1106
        shouldPadParensOutside = state;
 
1107
}
 
1108
 
 
1109
/**
 
1110
* set parenthesis inside padding mode.
 
1111
* options:
 
1112
*    true     statement parenthesis will be padded with spaces around them.
 
1113
*    false    statement parenthesis will not be padded.
 
1114
*
 
1115
* @param state         the padding mode.
 
1116
*/
 
1117
void ASFormatter::setParensInsidePaddingMode(bool state)
 
1118
{
 
1119
        shouldPadParensInside = state;
 
1120
}
 
1121
 
 
1122
/**
 
1123
* set parenthesis unpadding mode.
 
1124
* options:
 
1125
*    true     statement parenthesis will be unpadded with spaces removed around them.
 
1126
*    false    statement parenthesis will not be unpadded.
 
1127
*
 
1128
* @param state         the padding mode.
 
1129
*/
 
1130
void ASFormatter::setParensUnPaddingMode(bool state)
 
1131
{
 
1132
        shouldUnPadParens = state;
 
1133
}
 
1134
 
 
1135
/**
 
1136
 * set option to break/not break one-line blocks
 
1137
 *
 
1138
 * @param state        true = break, false = don't break.
 
1139
 */
 
1140
void ASFormatter::setBreakOneLineBlocksMode(bool state)
 
1141
{
 
1142
        shouldBreakOneLineBlocks = state;
 
1143
}
 
1144
 
 
1145
/**
 
1146
 * set option to break/not break lines consisting of multiple statements.
 
1147
 *
 
1148
 * @param state        true = break, false = don't break.
 
1149
 */
 
1150
void ASFormatter::setSingleStatementsMode(bool state)
 
1151
{
 
1152
        shouldBreakOneLineStatements = state;
 
1153
}
 
1154
 
 
1155
/**
 
1156
 * set option to convert tabs to spaces.
 
1157
 *
 
1158
 * @param state        true = convert, false = don't convert.
 
1159
 */
 
1160
void ASFormatter::setTabSpaceConversionMode(bool state)
 
1161
{
 
1162
        shouldConvertTabs = state;
 
1163
}
 
1164
 
 
1165
 
 
1166
/**
 
1167
 * set option to break unrelated blocks of code with empty lines.
 
1168
 *
 
1169
 * @param state        true = convert, false = don't convert.
 
1170
 */
 
1171
void ASFormatter::setBreakBlocksMode(bool state)
 
1172
{
 
1173
        shouldBreakBlocks = state;
 
1174
}
 
1175
 
 
1176
/**
 
1177
 * set option to break closing header blocks of code (such as 'else', 'catch', ...) with empty lines.
 
1178
 *
 
1179
 * @param state        true = convert, false = don't convert.
 
1180
 */
 
1181
void ASFormatter::setBreakClosingHeaderBlocksMode(bool state)
 
1182
{
 
1183
        shouldBreakClosingHeaderBlocks = state;
 
1184
}
 
1185
 
 
1186
/**
 
1187
 * jump over several characters.
 
1188
 *
 
1189
 * @param i       the number of characters to jump over.
 
1190
 */
 
1191
void ASFormatter::goForward(int i)
 
1192
{
 
1193
        while (--i >= 0)
 
1194
                getNextChar();
 
1195
}
 
1196
 
 
1197
/**
 
1198
* peek at the next unread character.
 
1199
*
 
1200
* @return     the next unread character.
 
1201
*/
 
1202
char ASFormatter::peekNextChar() const
 
1203
{
 
1204
        char ch = ' ';
 
1205
        size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
 
1206
 
 
1207
        if (peekNum == string::npos)
 
1208
                return ch;
 
1209
 
 
1210
        ch = currentLine[peekNum];
 
1211
 
 
1212
        return ch;
 
1213
}
 
1214
 
 
1215
/**
 
1216
* check if current placement is before a comment or line-comment
 
1217
*
 
1218
* @return     is before a comment or line-comment.
 
1219
*/
 
1220
bool ASFormatter::isBeforeComment() const
 
1221
{
 
1222
        bool foundComment = false;
 
1223
        size_t peekNum = currentLine.find_first_not_of(" \t", charNum + 1);
 
1224
 
 
1225
        if (peekNum == string::npos)
 
1226
                return foundComment;
 
1227
 
 
1228
        foundComment = (currentLine.compare(peekNum, 2, "/*") == 0
 
1229
                        || currentLine.compare(peekNum, 2, "//") == 0);
 
1230
 
 
1231
        return foundComment;
 
1232
}
 
1233
 
 
1234
/**
 
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
 
1237
*
 
1238
* @return     is before a comment or line-comment.
 
1239
*/
 
1240
bool ASFormatter::isBeforeLineEndComment(int startPos) const
 
1241
{
 
1242
        bool foundLineEndComment = false;
 
1243
        size_t peekNum = currentLine.find_first_not_of(" \t", startPos + 1);
 
1244
 
 
1245
        if (peekNum != string::npos)
 
1246
        {
 
1247
                if (currentLine.compare(peekNum, 2, "//") == 0)
 
1248
                        foundLineEndComment = true;
 
1249
                else if (currentLine.compare(peekNum, 2, "/*") == 0)
 
1250
                {
 
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;
 
1256
                }
 
1257
        }
 
1258
        return foundLineEndComment;
 
1259
}
 
1260
 
 
1261
 
 
1262
/**
 
1263
* get the next character, increasing the current placement in the process.
 
1264
* the new character is inserted into the variable currentChar.
 
1265
*
 
1266
* @return   whether succeded to receive the new character.
 
1267
*/
 
1268
bool ASFormatter::getNextChar()
 
1269
{
 
1270
        isInLineBreak = false;
 
1271
        previousChar = currentChar;
 
1272
 
 
1273
        if (!isWhiteSpace(currentChar))
 
1274
        {
 
1275
                previousNonWSChar = currentChar;
 
1276
                if (!isInComment && !isInLineComment && !isInQuote
 
1277
                        && !isImmediatelyPostComment
 
1278
                        && !isImmediatelyPostLineComment
 
1279
                        && !isSequenceReached("/*")
 
1280
                        && !isSequenceReached("//"))
 
1281
                        previousCommandChar = currentChar;
 
1282
        }
 
1283
 
 
1284
        int currentLineLength = currentLine.length();
 
1285
 
 
1286
        if (charNum + 1 < currentLineLength
 
1287
                && (!isWhiteSpace(peekNextChar()) || isInComment || isInLineComment))
 
1288
        {
 
1289
                currentChar = currentLine[++charNum];
 
1290
 
 
1291
                if (shouldConvertTabs && currentChar == '\t')
 
1292
                        currentChar = ' ';
 
1293
 
 
1294
                return true;
 
1295
        }
 
1296
        else        // end of line has been reached
 
1297
        {
 
1298
                if (sourceIterator->hasMoreLines())
 
1299
                {
 
1300
                        currentLine = sourceIterator->nextLine();
 
1301
                        // reset variables for new line
 
1302
                        spacePadNum = 0;
 
1303
                        inLineNumber++;
 
1304
                        isInCase = false;
 
1305
                        isInQuoteContinuation = isInVerbatimQuote | haveLineContinuationChar;
 
1306
                        haveLineContinuationChar= false;
 
1307
 
 
1308
                        if (currentLine.length() == 0)
 
1309
                        {
 
1310
                                currentLine = string(" ");        // a null is inserted if this is not done
 
1311
                        }
 
1312
 
 
1313
                        // unless reading in the first line of the file,
 
1314
                        // break a new line.
 
1315
                        if (!isVirgin)
 
1316
                                isInLineBreak = true;
 
1317
                        else
 
1318
                                isVirgin = false;
 
1319
 
 
1320
                        if (isInLineComment)
 
1321
                                isImmediatelyPostLineComment = true;
 
1322
                        isInLineComment = false;
 
1323
 
 
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;
 
1330
 
 
1331
                        trimNewLine();
 
1332
                        currentChar = currentLine[charNum];
 
1333
 
 
1334
                        if (shouldConvertTabs && currentChar == '\t')
 
1335
                                currentChar = ' ';
 
1336
 
 
1337
                        return true;
 
1338
                }
 
1339
                else
 
1340
                {
 
1341
                        endOfCodeReached = true;
 
1342
                        return false;
 
1343
                }
 
1344
        }
 
1345
}
 
1346
 
 
1347
/**
 
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.
 
1350
*/
 
1351
void ASFormatter::trimNewLine()
 
1352
{
 
1353
        int len = currentLine.length();
 
1354
        charNum = 0;
 
1355
 
 
1356
        if (isInComment || isInPreprocessor || isInQuoteContinuation)
 
1357
                return;
 
1358
 
 
1359
        while (isWhiteSpace(currentLine[charNum]) && charNum + 1 < len)
 
1360
                ++charNum;
 
1361
 
 
1362
        doesLineStartComment = false;
 
1363
        if (isSequenceReached("/*"))
 
1364
        {
 
1365
                charNum = 0;
 
1366
                doesLineStartComment = true;
 
1367
        }
 
1368
}
 
1369
 
 
1370
/**
 
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.
 
1376
 *
 
1377
 * @param ch               the character to append.
 
1378
 * @param canBreakLine     if true, a registered line-break
 
1379
 */
 
1380
void ASFormatter::appendChar(char ch, bool canBreakLine)
 
1381
{
 
1382
        if (canBreakLine && isInLineBreak)
 
1383
                breakLine();
 
1384
        formattedLine.append(1, ch);
 
1385
}
 
1386
 
 
1387
/**
 
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.
 
1393
 *
 
1394
 * @param sequence         the sequence to append.
 
1395
 * @param canBreakLine     if true, a registered line-break
 
1396
 */
 
1397
void ASFormatter::appendSequence(const string &sequence, bool canBreakLine)
 
1398
{
 
1399
        if (canBreakLine && isInLineBreak)
 
1400
                breakLine();
 
1401
        formattedLine.append(sequence);
 
1402
}
 
1403
 
 
1404
/**
 
1405
 * append a space to the current formattedline, UNLESS the
 
1406
 * last character is already a white-space character.
 
1407
 */
 
1408
void ASFormatter::appendSpacePad()
 
1409
{
 
1410
        int len = formattedLine.length();
 
1411
        if (len > 0 && !isWhiteSpace(formattedLine[len-1]))
 
1412
        {
 
1413
                formattedLine.append(1, ' ');
 
1414
                spacePadNum++;
 
1415
        }
 
1416
}
 
1417
 
 
1418
/**
 
1419
 * append a space to the current formattedline, UNLESS the
 
1420
 * next character is already a white-space character.
 
1421
 */
 
1422
void ASFormatter::appendSpaceAfter()
 
1423
{
 
1424
        int len = currentLine.length();
 
1425
        if (charNum + 1 < len && !isWhiteSpace(currentLine[charNum+1]))
 
1426
        {
 
1427
                formattedLine.append(1, ' ');
 
1428
                spacePadNum++;
 
1429
        }
 
1430
}
 
1431
 
 
1432
/**
 
1433
 * register a line break for the formatted line.
 
1434
 */
 
1435
void ASFormatter::breakLine()
 
1436
{
 
1437
        isLineReady = true;
 
1438
        isInLineBreak = false;
 
1439
        spacePadNum = 0;
 
1440
        formattedLineCommentNum = string::npos;
 
1441
 
 
1442
        // queue an empty line prepend request if one exists
 
1443
        prependEmptyLine = isPrependPostBlockEmptyLineRequested;
 
1444
 
 
1445
        readyFormattedLine =  formattedLine;
 
1446
        if (isAppendPostBlockEmptyLineRequested)
 
1447
        {
 
1448
                isAppendPostBlockEmptyLineRequested = false;
 
1449
                isPrependPostBlockEmptyLineRequested = true;
 
1450
        }
 
1451
        else
 
1452
        {
 
1453
                isPrependPostBlockEmptyLineRequested = false;
 
1454
        }
 
1455
 
 
1456
        formattedLine = "";
 
1457
}
 
1458
 
 
1459
/**
 
1460
 * check if the currently reached open-bracket (i.e. '{')
 
1461
 * opens a:
 
1462
 * - a definition type block (such as a class or namespace),
 
1463
 * - a command block (such as a method block)
 
1464
 * - a static array
 
1465
 * this method takes for granted that the current character
 
1466
 * is an opening bracket.
 
1467
 *
 
1468
 * @return    the type of the opened block.
 
1469
 */
 
1470
BracketType ASFormatter::getBracketType()
 
1471
{
 
1472
        BracketType returnVal;
 
1473
 
 
1474
        if (previousNonWSChar == '=')
 
1475
                returnVal = ARRAY_TYPE;
 
1476
        else if (foundPreDefinitionHeader)
 
1477
        {
 
1478
                returnVal = DEFINITION_TYPE;
 
1479
                if (foundNamespaceHeader)
 
1480
                        returnVal = (BracketType)(returnVal | NAMESPACE_TYPE);
 
1481
                else if (foundClassHeader)
 
1482
                        returnVal = (BracketType)(returnVal | CLASS_TYPE);
 
1483
        }
 
1484
        else
 
1485
        {
 
1486
                bool isCommandType = (foundPreCommandHeader
 
1487
                                      || (currentHeader != NULL && isNonParenHeader)
 
1488
                                      || (previousCommandChar == ')')
 
1489
                                      || (previousCommandChar == ':' && !foundQuestionMark)
 
1490
                                      || (previousCommandChar == ';')
 
1491
                                      || ((previousCommandChar == '{' ||  previousCommandChar == '}')
 
1492
                                          && isPreviousBracketBlockRelated));
 
1493
 
 
1494
                if (!isCommandType && isSharpStyle && isNextWordSharpAccessor())
 
1495
                {
 
1496
                        isCommandType = true;
 
1497
                        isSharpAccessor = true;
 
1498
                }
 
1499
 
 
1500
                returnVal = (isCommandType ? COMMAND_TYPE : ARRAY_TYPE);
 
1501
        }
 
1502
 
 
1503
        if (isOneLineBlockReached())
 
1504
                returnVal = (BracketType)(returnVal | SINGLE_LINE_TYPE);
 
1505
 
 
1506
        TRbracket(returnVal);
 
1507
 
 
1508
        return returnVal;
 
1509
}
 
1510
 
 
1511
 
 
1512
/**
 
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 '&'.
 
1517
 *
 
1518
 * @return        whether current character is a reference-or-pointer
 
1519
 */
 
1520
bool ASFormatter::isPointerOrReference() const
 
1521
{
 
1522
        bool isPR;
 
1523
        isPR = (!isInPotentialCalculation
 
1524
                || IS_A(bracketTypeStack->back(), DEFINITION_TYPE)
 
1525
                || (!isLegalNameChar(previousNonWSChar)
 
1526
                    && previousNonWSChar != ')'
 
1527
                    && previousNonWSChar != ']')
 
1528
               );
 
1529
 
 
1530
        if (!isPR)
 
1531
        {
 
1532
                char nextChar = peekNextChar();
 
1533
                isPR |= (!isWhiteSpace(nextChar)
 
1534
                         && nextChar != '-'
 
1535
                         && nextChar != '('
 
1536
                         && nextChar != '['
 
1537
                         && !isLegalNameChar(nextChar));
 
1538
        }
 
1539
 
 
1540
        return isPR;
 
1541
}
 
1542
 
 
1543
 
 
1544
/**
 
1545
 * check if the currently reached '-' character is
 
1546
 * a unary minus
 
1547
 * this method takes for granted that the current character
 
1548
 * is a '-'.
 
1549
 *
 
1550
 * @return        whether the current '-' is a unary minus.
 
1551
 */
 
1552
bool ASFormatter::isUnaryMinus() const
 
1553
{
 
1554
        return ((previousOperator == &AS_RETURN || !isalnum(previousCommandChar))
 
1555
                && previousCommandChar != '.'
 
1556
                && previousCommandChar != ')'
 
1557
                && previousCommandChar != ']');
 
1558
}
 
1559
 
 
1560
 
 
1561
/**
 
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
 
1565
 * is a '-' or '+'.
 
1566
 *
 
1567
 * @return        whether the current '-' is in an exponent.
 
1568
 */
 
1569
bool ASFormatter::isInExponent() const
 
1570
{
 
1571
        int formattedLineLength = formattedLine.length();
 
1572
        if (formattedLineLength >= 2)
 
1573
        {
 
1574
                char prevPrevFormattedChar = formattedLine[formattedLineLength - 2];
 
1575
                char prevFormattedChar = formattedLine[formattedLineLength - 1];
 
1576
 
 
1577
                return ((prevFormattedChar == 'e' || prevFormattedChar == 'E')
 
1578
                        && (prevPrevFormattedChar == '.' || isdigit(prevPrevFormattedChar)));
 
1579
        }
 
1580
        else
 
1581
                return false;
 
1582
}
 
1583
 
 
1584
/**
 
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,
 
1588
 *.
 
1589
 * @return        has a one-line bracket been reached?
 
1590
 */
 
1591
bool ASFormatter::isOneLineBlockReached() const
 
1592
{
 
1593
        bool isInComment = false;
 
1594
        bool isInQuote = false;
 
1595
        int bracketCount = 1;
 
1596
        int currentLineLength = currentLine.length();
 
1597
        char quoteChar = ' ';
 
1598
 
 
1599
        for (int i = charNum + 1; i < currentLineLength; ++i)
 
1600
        {
 
1601
                char ch = currentLine[i];
 
1602
 
 
1603
                if (isInComment)
 
1604
                {
 
1605
                        if (currentLine.compare(i, 2, "*/") == 0)
 
1606
                        {
 
1607
                                isInComment = false;
 
1608
                                ++i;
 
1609
                        }
 
1610
                        continue;
 
1611
                }
 
1612
 
 
1613
                if (ch == '\\')
 
1614
                {
 
1615
                        ++i;
 
1616
                        continue;
 
1617
                }
 
1618
 
 
1619
                if (isInQuote)
 
1620
                {
 
1621
                        if (ch == quoteChar)
 
1622
                                isInQuote = false;
 
1623
                        continue;
 
1624
                }
 
1625
 
 
1626
                if (ch == '"' || ch == '\'')
 
1627
                {
 
1628
                        isInQuote = true;
 
1629
                        quoteChar = ch;
 
1630
                        continue;
 
1631
                }
 
1632
 
 
1633
                if (currentLine.compare(i, 2, "//") == 0)
 
1634
                        break;
 
1635
 
 
1636
                if (currentLine.compare(i, 2, "/*") == 0)
 
1637
                {
 
1638
                        isInComment = true;
 
1639
                        ++i;
 
1640
                        continue;
 
1641
                }
 
1642
 
 
1643
                if (ch == '{')
 
1644
                        ++bracketCount;
 
1645
                else if (ch == '}')
 
1646
                        --bracketCount;
 
1647
 
 
1648
                if (bracketCount == 0)
 
1649
                        return true;
 
1650
        }
 
1651
 
 
1652
        return false;
 
1653
}
 
1654
 
 
1655
/**
 
1656
 * check if one of a set of headers has been reached in the
 
1657
 * current position of the current line.
 
1658
 *
 
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
 
1662
 */
 
1663
const string *ASFormatter::findHeader(const vector<const string*> &headers, bool checkBoundry)
 
1664
{
 
1665
        return ASBeautifier::findHeader(currentLine, charNum, headers, checkBoundry);
 
1666
}
 
1667
 
 
1668
/**
 
1669
 * check if a line begins with the specified character
 
1670
 * i.e. if the current line begins with a open bracket.
 
1671
 *
 
1672
 * @return        true or false
 
1673
 */
 
1674
bool ASFormatter::lineBeginsWith(char charToCheck) const
 
1675
{
 
1676
        bool beginsWith = false;
 
1677
        size_t i = currentLine.find_first_not_of(" \t");
 
1678
 
 
1679
        if (i != string::npos)
 
1680
                if (currentLine[i] == charToCheck && (int) i == charNum)
 
1681
                        beginsWith = true;
 
1682
 
 
1683
        return beginsWith;
 
1684
}
 
1685
 
 
1686
/**
 
1687
* peek at the next word to determine if it is a C# accessor.
 
1688
* will look ahead in the input file if necessary.
 
1689
*
 
1690
* @return       true if the next word is get or set.
 
1691
*/
 
1692
bool ASFormatter::isNextWordSharpAccessor() const
 
1693
{
 
1694
        bool retVal = false;
 
1695
        string nextLine;
 
1696
        size_t firstChar;
 
1697
 
 
1698
        firstChar = currentLine.find_first_not_of(" \t", charNum + 1);
 
1699
 
 
1700
        if (firstChar != string::npos)
 
1701
        {
 
1702
                nextLine = currentLine.substr(firstChar);
 
1703
                firstChar = 0;
 
1704
        }
 
1705
        else
 
1706
        {
 
1707
                // find the first non-blank line
 
1708
                while (hasMoreLines())
 
1709
                {
 
1710
                        nextLine = sourceIterator->peekNextLine();
 
1711
                        firstChar = nextLine.find_first_not_of(" \t");
 
1712
                        if (firstChar != string::npos)
 
1713
                                break;
 
1714
                }
 
1715
                sourceIterator->peekReset();
 
1716
        }
 
1717
 
 
1718
        if (hasMoreLines())
 
1719
                if (findKeyword(nextLine, firstChar, "get") || findKeyword(nextLine, firstChar, "set"))
 
1720
                        retVal = true;
 
1721
 
 
1722
        return retVal;
 
1723
}
 
1724
 
 
1725
/**
 
1726
 * adjust comment position because of adding or deleting spaces
 
1727
 * the spaces are added or deleted to formattedLine
 
1728
 * spacePadNum contains the adjustment
 
1729
 */
 
1730
void ASFormatter::adjustComments(void)
 
1731
{
 
1732
        assert(spacePadNum != 0);
 
1733
        assert(currentLine.compare(charNum, 2, "//") == 0
 
1734
               || currentLine.compare(charNum, 2, "/*") == 0);
 
1735
 
 
1736
 
 
1737
        // block comment must be closed on this line with nothing after it
 
1738
        if (currentLine.compare(charNum, 2, "/*") == 0)
 
1739
        {
 
1740
                size_t endNum = currentLine.find("*/", charNum + 2);
 
1741
                if (endNum == string::npos)
 
1742
                        return;
 
1743
                if (currentLine.find_first_not_of(" \t", endNum + 2) != string::npos)
 
1744
                        return;
 
1745
        }
 
1746
 
 
1747
        size_t len = formattedLine.length();
 
1748
        // if spaces were removed, need to add spaces before the comment
 
1749
        if (spacePadNum < 0)
 
1750
        {
 
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
 
1755
//                      adjust = 0;
 
1756
//              TRcomment(adjust);                  // trace macro
 
1757
        }
 
1758
        // if spaces were added, need to delete spaces before the comment, if possible
 
1759
        else if (spacePadNum > 0)
 
1760
        {
 
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
 
1766
                //else
 
1767
                //    adjust = 0;
 
1768
                TRcomment(-adjust);                 // trace macro
 
1769
        }
 
1770
}
 
1771
 
 
1772
/**
 
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
 
1776
 */
 
1777
void ASFormatter::appendCharInsideComments(void)
 
1778
{
 
1779
        if (formattedLineCommentNum == string::npos             // does the comment start on the previous line?
 
1780
                || isBeforeComment())                                   // does a comment follow on this line?
 
1781
        {
 
1782
                appendCurrentChar();                                            // don't attach
 
1783
                return;
 
1784
        }
 
1785
        assert(formattedLine.compare(formattedLineCommentNum, 2, "//") == 0
 
1786
               || formattedLine.compare(formattedLineCommentNum, 2, "/*") == 0);
 
1787
 
 
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?
 
1792
        {
 
1793
                appendCurrentChar();                            // don't attach
 
1794
                return;
 
1795
        }
 
1796
        beg++;
 
1797
 
 
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;
 
1804
}
 
1805
 
 
1806
/**
 
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
 
1811
 *
 
1812
 * @param *newOperator     the operator to be padded
 
1813
 */
 
1814
void ASFormatter::padOperators(const string *newOperator)
 
1815
{
 
1816
        assert (shouldPadOperators);
 
1817
        assert(newOperator != NULL);
 
1818
 
 
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))
 
1843
                          && !isInCase
 
1844
                         );
 
1845
 
 
1846
        // pad before operator
 
1847
        if (shouldPad
 
1848
                && !isInBlParen
 
1849
                && !(newOperator == &AS_COLON && !foundQuestionMark)
 
1850
                && newOperator != &AS_SEMICOLON
 
1851
                && newOperator != &AS_COMMA)
 
1852
                appendSpacePad();
 
1853
        appendSequence(*newOperator);
 
1854
        goForward(newOperator->length() - 1);
 
1855
 
 
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()--;
 
1861
 
 
1862
        currentChar = (*newOperator)[newOperator->length() - 1];
 
1863
        // pad after operator
 
1864
        // but do not pad after a '-' that is a unary-minus.
 
1865
        if (shouldPad
 
1866
                && !isInBlParen
 
1867
                && !isBeforeComment()
 
1868
                && !(newOperator == &AS_MINUS && isUnaryMinus())
 
1869
                && !(currentLine.compare(charNum + 1, 1,  ";") == 0)
 
1870
                && !(currentLine.compare(charNum + 1, 2, "::") == 0))
 
1871
                appendSpaceAfter();
 
1872
 
 
1873
        previousOperator = newOperator;
 
1874
        return;
 
1875
}
 
1876
 
 
1877
/**
 
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
 
1882
 */
 
1883
void ASFormatter::padParens(void)
 
1884
{
 
1885
        assert(shouldPadParensOutside || shouldPadParensInside || shouldUnPadParens);
 
1886
        assert (currentChar == '(' || currentChar == ')');
 
1887
 
 
1888
        if (currentChar == '(')
 
1889
        {
 
1890
                int spacesOutsideToDelete = formattedLine.length() - 1;
 
1891
                int spacesInsideToDelete = 0;
 
1892
 
 
1893
                // compute spaces outside the opening paren to delete
 
1894
                if (shouldUnPadParens)
 
1895
                {
 
1896
                        char lastChar = ' ';
 
1897
                        bool prevIsParenHeader = false;
 
1898
                        size_t i = formattedLine.find_last_not_of(" \t");
 
1899
                        if (i != string::npos)
 
1900
                        {
 
1901
                                size_t end = i;
 
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--)
 
1907
                                {
 
1908
                                        if (isLegalNameChar(formattedLine[start]) || formattedLine[start] == '*')
 
1909
                                                continue;
 
1910
                                        start++;
 
1911
                                        break;
 
1912
                                }
 
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)
 
1917
                                {
 
1918
                                        prevIsParenHeader = true;
 
1919
                                        TRxtra(*prevWordH);         // trace macro
 
1920
                                }
 
1921
                                else if (prevWord == "return"   // don't unpad return statements
 
1922
                                         || prevWord == "*")     // don't unpad multiply or pointer
 
1923
                                {
 
1924
                                        prevIsParenHeader = true;
 
1925
                                        TRxtra(prevWord);           // trace macro
 
1926
                                }
 
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"
 
1941
                                        )
 
1942
                                {
 
1943
                                        prevIsParenHeader = true;
 
1944
                                        TRxtra(prevWord);           // trace macro
 
1945
                                }
 
1946
                        }
 
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 &&
 
1952
                                 || lastChar == ','
 
1953
                                 || (lastChar == '>' && !foundCastOperator)
 
1954
                                 || lastChar == '<'
 
1955
                                 || lastChar == '?'
 
1956
                                 || lastChar == ':'
 
1957
                                 || lastChar == ';'
 
1958
                                 || lastChar == '='
 
1959
                                 || lastChar == '+'
 
1960
                                 || lastChar == '-'
 
1961
                                 || (lastChar == '*' && isInPotentialCalculation)
 
1962
                                 || lastChar == '/'
 
1963
                                 || lastChar == '%')
 
1964
                                spacesOutsideToDelete--;
 
1965
 
 
1966
                        if (spacesOutsideToDelete > 0)
 
1967
                        {
 
1968
                                formattedLine.erase(i + 1, spacesOutsideToDelete);
 
1969
                                spacePadNum -= spacesOutsideToDelete;
 
1970
                        }
 
1971
                }
 
1972
 
 
1973
                // pad open paren outside
 
1974
                char peekedCharOutside = peekNextChar();
 
1975
                if (shouldPadParensOutside)
 
1976
                        if (!(currentChar == '(' && peekedCharOutside == ')'))
 
1977
                                appendSpacePad();
 
1978
 
 
1979
                appendCurrentChar();
 
1980
 
 
1981
                // unpad open paren inside
 
1982
                if (shouldUnPadParens)
 
1983
                {
 
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)
 
1990
                        {
 
1991
                                currentLine.erase(charNum + 1, spacesInsideToDelete);
 
1992
                                spacePadNum -= spacesInsideToDelete;
 
1993
                        }
 
1994
                }
 
1995
 
 
1996
                // pad open paren inside
 
1997
                char peekedCharInside = peekNextChar();
 
1998
                if (shouldPadParensInside)
 
1999
                        if (!(currentChar == '(' && peekedCharInside == ')'))
 
2000
                                appendSpaceAfter();
 
2001
 
 
2002
                TRunpad('(', spacesOutsideToDelete, spacesInsideToDelete);       // trace macro
 
2003
        }
 
2004
        else if (currentChar == ')' /*|| currentChar == ']'*/)
 
2005
        {
 
2006
                int spacesOutsideToDelete = 0;
 
2007
                int spacesInsideToDelete = formattedLine.length();
 
2008
 
 
2009
                // unpad close paren inside
 
2010
                if (shouldUnPadParens)
 
2011
                {
 
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)
 
2018
                        {
 
2019
                                formattedLine.erase(i + 1, spacesInsideToDelete);
 
2020
                                spacePadNum -= spacesInsideToDelete;
 
2021
                        }
 
2022
                }
 
2023
 
 
2024
                // pad close paren inside
 
2025
                if (shouldPadParensInside)
 
2026
                        if (!(previousChar == '(' && currentChar == ')'))
 
2027
                                appendSpacePad();
 
2028
 
 
2029
                appendCurrentChar();
 
2030
 
 
2031
                // unpad close paren outside
 
2032
                if (shouldUnPadParens)
 
2033
                {
 
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--;
 
2041
 
 
2042
                        if (spacesOutsideToDelete > 0)
 
2043
                        {
 
2044
                                currentLine.erase(charNum + 1, spacesOutsideToDelete);
 
2045
                                spacePadNum -= spacesOutsideToDelete;
 
2046
                        }
 
2047
                }
 
2048
 
 
2049
                // pad close paren outside
 
2050
                char peekedCharOutside = peekNextChar();
 
2051
                if (shouldPadParensOutside)
 
2052
                        if (peekedCharOutside != ';'
 
2053
                                && peekedCharOutside != ','
 
2054
                                && peekedCharOutside != '.'
 
2055
                                && peekedCharOutside != '-')    // check for ->
 
2056
                                appendSpaceAfter();
 
2057
 
 
2058
                TRunpad(')', spacesInsideToDelete, 0 /*spacesOutsideToDelete*/);       // trace macro
 
2059
        }
 
2060
        return;
 
2061
}
 
2062
 
 
2063
/**
 
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
 
2068
 *
 
2069
 * @param bracketType    the type of bracket to be formatted.
 
2070
 */
 
2071
void ASFormatter::formatBrackets(BracketType bracketType)
 
2072
{
 
2073
        assert(!IS_A(bracketType, ARRAY_TYPE));
 
2074
        assert (currentChar == '{' || currentChar == '}');
 
2075
 
 
2076
        if (currentChar == '{')
 
2077
        {
 
2078
                parenStack->push_back(0);
 
2079
        }
 
2080
        else if (currentChar == '}')
 
2081
        {
 
2082
                // parenStack must contain one entry
 
2083
                if (parenStack->size() > 1)
 
2084
                {
 
2085
                        parenStack->pop_back();
 
2086
                }
 
2087
        }
 
2088
 
 
2089
        if (currentChar == '{')
 
2090
        {
 
2091
                bool bdacBreak = false;
 
2092
                // should a Linux bracket be broken?
 
2093
                if (bracketFormatMode == BDAC_MODE)
 
2094
                {
 
2095
                        // always break a class
 
2096
                        if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], CLASS_TYPE))
 
2097
                                bdacBreak = true;
 
2098
                        // break a namespace and the first bracket if a function
 
2099
                        else if (bracketTypeStack->size() <= 2)
 
2100
                        {
 
2101
                                if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], NAMESPACE_TYPE)
 
2102
                                        || IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], COMMAND_TYPE))
 
2103
                                        bdacBreak = true;
 
2104
                        }
 
2105
                        // break the first bracket after a namespace if a function
 
2106
                        else if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], NAMESPACE_TYPE))
 
2107
                        {
 
2108
                                if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], COMMAND_TYPE))
 
2109
                                        bdacBreak = true;
 
2110
                        }
 
2111
                        // if not C style then break the first bracket after a class if a function
 
2112
                        else if (!isCStyle)
 
2113
                        {
 
2114
                                if (IS_A((*bracketTypeStack)[bracketTypeStack->size()-2], CLASS_TYPE)
 
2115
                                        && IS_A((*bracketTypeStack)[bracketTypeStack->size()-1], COMMAND_TYPE))
 
2116
                                        bdacBreak = true;
 
2117
                        }
 
2118
                }
 
2119
                if (bracketFormatMode == ATTACH_MODE
 
2120
                        || (bracketFormatMode == BDAC_MODE && !bdacBreak))
 
2121
                {
 
2122
                        // are there comments before the bracket?
 
2123
                        if (isCharImmediatelyPostComment || isCharImmediatelyPostLineComment)
 
2124
                        {
 
2125
                                if ((shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE))
 
2126
                                        && peekNextChar() != '}'
 
2127
                                        && previousCommandChar != '{')  // don't attach { {
 
2128
                                        appendCharInsideComments();
 
2129
                                else
 
2130
                                        appendCurrentChar();                    // don't attach
 
2131
                        }
 
2132
                        else if (previousCommandChar == '{'
 
2133
                                 || previousCommandChar == '}'
 
2134
                                 || previousCommandChar == ';')  // '}' , ';' chars added for proper handling of '{' immediately after a '}' or ';'
 
2135
                        {
 
2136
                                appendCurrentChar();                            // don't attach
 
2137
                        }
 
2138
                        else
 
2139
                        {
 
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('{')))
 
2149
                                {
 
2150
                                        appendSpacePad();
 
2151
                                        appendCurrentChar(false);               // OK to attach
 
2152
                                }
 
2153
                                else
 
2154
                                {
 
2155
                                        if (!isInLineBreak)
 
2156
                                                appendSpacePad();
 
2157
                                        appendCurrentChar();                    // don't attach
 
2158
                                }
 
2159
                        }
 
2160
                }
 
2161
                else if (bracketFormatMode == BREAK_MODE
 
2162
                         || (bracketFormatMode == BDAC_MODE && bdacBreak))
 
2163
                {
 
2164
                        if (isBeforeComment()
 
2165
                                && (shouldBreakOneLineBlocks || !IS_A(bracketType, SINGLE_LINE_TYPE)))
 
2166
                        {
 
2167
                                // if comment is at line end leave the comment on this line
 
2168
                                if (isBeforeLineEndComment(charNum) && !lineBeginsWith('{'))
 
2169
                                {
 
2170
                                        currentChar = ' ';                              // remove bracket from current line
 
2171
                                        appendOpeningBracket = true;    // append bracket to following line
 
2172
                                }
 
2173
                                // else put comment after the bracket
 
2174
                                else
 
2175
                                        breakLine();
 
2176
                        }
 
2177
                        else if (!IS_A(bracketType,  SINGLE_LINE_TYPE))
 
2178
                                breakLine();
 
2179
                        else if (shouldBreakOneLineBlocks && peekNextChar() != '}')
 
2180
                                breakLine();
 
2181
                        else if (!isInLineBreak)
 
2182
                                appendSpacePad();
 
2183
 
 
2184
                        appendCurrentChar();
 
2185
                }
 
2186
                else if (bracketFormatMode == NONE_MODE)
 
2187
                {
 
2188
                        if (lineBeginsWith('{'))                                // is opening bracket broken?
 
2189
                                appendCurrentChar();                            // don't attach
 
2190
                        else
 
2191
                        {
 
2192
                                appendSpacePad();
 
2193
                                appendCurrentChar(false);                       // OK to attach
 
2194
                        }
 
2195
                }
 
2196
        }
 
2197
        else if (currentChar == '}')
 
2198
        {
 
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;
 
2203
 
 
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
 
2208
                {
 
2209
                        breakLine();
 
2210
                        appendCurrentChar();
 
2211
                }
 
2212
                else
 
2213
                {
 
2214
                        if (!isCharImmediatelyPostComment
 
2215
                                && !bracketFormatMode == NONE_MODE
 
2216
                                && !isImmediatelyPostEmptyBlock)
 
2217
                                isInLineBreak = false;
 
2218
 
 
2219
                        appendCurrentChar();
 
2220
 
 
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;
 
2225
                }
 
2226
 
 
2227
                if (shouldBreakBlocks)
 
2228
                {
 
2229
                        isAppendPostBlockEmptyLineRequested = true;
 
2230
                }
 
2231
        }
 
2232
        return;
 
2233
}
 
2234
 
 
2235
/**
 
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
 
2241
 *
 
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.
 
2244
 */
 
2245
void ASFormatter::formatArrayBrackets(BracketType bracketType, bool isOpeningArrayBracket)
 
2246
{
 
2247
        assert(IS_A(bracketType, ARRAY_TYPE));
 
2248
        assert (currentChar == '{' || currentChar == '}');
 
2249
 
 
2250
        if (currentChar == '{')
 
2251
        {
 
2252
                // is this the first opening bracket in the array?
 
2253
                if (isOpeningArrayBracket)
 
2254
                {
 
2255
                        if (bracketFormatMode == ATTACH_MODE || bracketFormatMode == BDAC_MODE)
 
2256
                        {
 
2257
                                // don't attach to a preprocessor directive
 
2258
                                if (isImmediatelyPostPreprocessor && lineBeginsWith('{'))
 
2259
                                {
 
2260
                                        isInLineBreak = true;
 
2261
                                        appendCurrentChar();                            // don't attach
 
2262
                                }
 
2263
                                // are there comments before the bracket?
 
2264
                                else if (isCharImmediatelyPostComment || isCharImmediatelyPostLineComment)
 
2265
                                {
 
2266
                                        appendCharInsideComments();
 
2267
                                }
 
2268
                                else
 
2269
                                {
 
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
 
2274
                                        else
 
2275
                                        {
 
2276
                                                // if bracket is broken or not an assignment
 
2277
                                                if (lineBeginsWith('{') || previousNonWSChar != '=')
 
2278
                                                        appendSpacePad();
 
2279
                                                appendCurrentChar(false);                       // OK to attach
 
2280
                                        }
 
2281
                                }
 
2282
                        }
 
2283
                        else if (bracketFormatMode == BREAK_MODE)
 
2284
                        {
 
2285
                                if (isWhiteSpace(peekNextChar()))
 
2286
                                        breakLine();
 
2287
                                else if (isBeforeComment())
 
2288
                                {
 
2289
                                        // do not break unless comment is at line end
 
2290
                                        if (isBeforeLineEndComment(charNum))
 
2291
                                        {
 
2292
                                                currentChar = ' ';                              // remove bracket from current line
 
2293
                                                appendOpeningBracket = true;    // append bracket to following line
 
2294
                                        }
 
2295
                                }
 
2296
                                if (!isInLineBreak && previousNonWSChar != '=')
 
2297
                                        appendSpacePad();
 
2298
                                appendCurrentChar();
 
2299
                        }
 
2300
                        else if (bracketFormatMode == NONE_MODE)
 
2301
                        {
 
2302
                                if (lineBeginsWith('{'))                // is opening bracket broken?
 
2303
                                {
 
2304
                                        appendCurrentChar();                            // don't attach
 
2305
                                }
 
2306
                                else
 
2307
                                {
 
2308
                                        // if bracket is broken or not an assignment
 
2309
                                        if (lineBeginsWith('{') || previousNonWSChar != '=')
 
2310
                                                appendSpacePad();
 
2311
                                        appendCurrentChar(false);                       // OK to attach
 
2312
                                }
 
2313
                        }
 
2314
                }
 
2315
                else
 
2316
                        appendCurrentChar();     // not the first opening bracket - don't change
 
2317
 
 
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)
 
2322
                        || nextChar == '{')
 
2323
                        isNonInStatementArray = true;
 
2324
                if (isNonInStatementArray)
 
2325
                        TRarray('x');
 
2326
                else
 
2327
                        TRarray(' ');
 
2328
 
 
2329
        }
 
2330
        else if (currentChar == '}')
 
2331
        {
 
2332
                // does this close the first opening bracket in the array?
 
2333
                if (isOpeningArrayBracket && !IS_A(bracketType, SINGLE_LINE_TYPE) )
 
2334
                {
 
2335
                        breakLine();
 
2336
                        appendCurrentChar();
 
2337
                }
 
2338
                else
 
2339
                        appendCurrentChar();
 
2340
        }
 
2341
}
 
2342
 
 
2343
 
 
2344
}   // end namespace astyle